aboutsummaryrefslogtreecommitdiffstats
path: root/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util
diff options
context:
space:
mode:
Diffstat (limited to 'kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util')
-rw-r--r--kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/clock.go218
-rw-r--r--kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/crypto/crypto.go190
-rw-r--r--kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/doc.go20
-rw-r--r--kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/errors/doc.go18
-rw-r--r--kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/errors/errors.go156
-rw-r--r--kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/flowcontrol/backoff.go149
-rw-r--r--kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/flowcontrol/throttle.go116
-rw-r--r--kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/framer/framer.go167
-rw-r--r--kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/hash/hash.go37
-rw-r--r--kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/homedir/homedir.go40
-rw-r--r--kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/integer/integer.go67
-rw-r--r--kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/intstr/generated.pb.go347
-rw-r--r--kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/intstr/generated.proto42
-rw-r--r--kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/intstr/intstr.go147
-rw-r--r--kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/json/json.go107
-rw-r--r--kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/line_delimiter.go63
-rw-r--r--kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/logs.go61
-rw-r--r--kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/net/http.go235
-rw-r--r--kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/net/interface.go278
-rw-r--r--kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/net/port_range.go108
-rw-r--r--kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/net/port_split.go77
-rw-r--r--kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/net/sets/README.md17
-rw-r--r--kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/net/sets/ipnet.go119
-rw-r--r--kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/net/util.go36
-rw-r--r--kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/parsers/parsers.go54
-rw-r--r--kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/rand/rand.go83
-rw-r--r--kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/resource_container_linux.go49
-rw-r--r--kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/resource_container_unsupported.go31
-rw-r--r--kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/runner.go58
-rw-r--r--kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/runtime/runtime.go94
-rw-r--r--kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/sets/byte.go194
-rw-r--r--kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/sets/doc.go20
-rw-r--r--kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/sets/empty.go23
-rw-r--r--kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/sets/int.go194
-rw-r--r--kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/sets/int64.go194
-rw-r--r--kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/sets/string.go194
-rw-r--r--kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/string_flag.go56
-rw-r--r--kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/template.go48
-rw-r--r--kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/trace.go72
-rw-r--r--kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/umask.go27
-rw-r--r--kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/umask_windows.go27
-rw-r--r--kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/util.go147
-rw-r--r--kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/uuid.go42
-rw-r--r--kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/validation/field/errors.go228
-rw-r--r--kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/validation/field/path.go91
-rw-r--r--kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/validation/validation.go306
-rw-r--r--kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/wait/doc.go19
-rw-r--r--kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/wait/wait.go268
-rw-r--r--kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/yaml/decoder.go247
49 files changed, 5581 insertions, 0 deletions
diff --git a/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/clock.go b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/clock.go
new file mode 100644
index 0000000..71aca9e
--- /dev/null
+++ b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/clock.go
@@ -0,0 +1,218 @@
+/*
+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 util
+
+import (
+ "sync"
+ "time"
+)
+
+// Clock allows for injecting fake or real clocks into code that
+// needs to do arbitrary things based on time.
+type Clock interface {
+ Now() time.Time
+ Since(time.Time) time.Duration
+ After(d time.Duration) <-chan time.Time
+ Sleep(d time.Duration)
+ Tick(d time.Duration) <-chan time.Time
+}
+
+var (
+ _ = Clock(RealClock{})
+ _ = Clock(&FakeClock{})
+ _ = Clock(&IntervalClock{})
+)
+
+// RealClock really calls time.Now()
+type RealClock struct{}
+
+// Now returns the current time.
+func (RealClock) Now() time.Time {
+ return time.Now()
+}
+
+// Since returns time since the specified timestamp.
+func (RealClock) Since(ts time.Time) time.Duration {
+ return time.Since(ts)
+}
+
+// Same as time.After(d).
+func (RealClock) After(d time.Duration) <-chan time.Time {
+ return time.After(d)
+}
+
+func (RealClock) Tick(d time.Duration) <-chan time.Time {
+ return time.Tick(d)
+}
+
+func (RealClock) Sleep(d time.Duration) {
+ time.Sleep(d)
+}
+
+// FakeClock implements Clock, but returns an arbitrary time.
+type FakeClock struct {
+ lock sync.RWMutex
+ time time.Time
+
+ // waiters are waiting for the fake time to pass their specified time
+ waiters []fakeClockWaiter
+}
+
+type fakeClockWaiter struct {
+ targetTime time.Time
+ stepInterval time.Duration
+ skipIfBlocked bool
+ destChan chan<- time.Time
+}
+
+func NewFakeClock(t time.Time) *FakeClock {
+ return &FakeClock{
+ time: t,
+ }
+}
+
+// Now returns f's time.
+func (f *FakeClock) Now() time.Time {
+ f.lock.RLock()
+ defer f.lock.RUnlock()
+ return f.time
+}
+
+// Since returns time since the time in f.
+func (f *FakeClock) Since(ts time.Time) time.Duration {
+ f.lock.RLock()
+ defer f.lock.RUnlock()
+ return f.time.Sub(ts)
+}
+
+// Fake version of time.After(d).
+func (f *FakeClock) After(d time.Duration) <-chan time.Time {
+ f.lock.Lock()
+ defer f.lock.Unlock()
+ stopTime := f.time.Add(d)
+ ch := make(chan time.Time, 1) // Don't block!
+ f.waiters = append(f.waiters, fakeClockWaiter{
+ targetTime: stopTime,
+ destChan: ch,
+ })
+ return ch
+}
+
+func (f *FakeClock) Tick(d time.Duration) <-chan time.Time {
+ f.lock.Lock()
+ defer f.lock.Unlock()
+ tickTime := f.time.Add(d)
+ ch := make(chan time.Time, 1) // hold one tick
+ f.waiters = append(f.waiters, fakeClockWaiter{
+ targetTime: tickTime,
+ stepInterval: d,
+ skipIfBlocked: true,
+ destChan: ch,
+ })
+
+ return ch
+}
+
+// Move clock by Duration, notify anyone that's called After or Tick
+func (f *FakeClock) Step(d time.Duration) {
+ f.lock.Lock()
+ defer f.lock.Unlock()
+ f.setTimeLocked(f.time.Add(d))
+}
+
+// Sets the time.
+func (f *FakeClock) SetTime(t time.Time) {
+ f.lock.Lock()
+ defer f.lock.Unlock()
+ f.setTimeLocked(t)
+}
+
+// Actually changes the time and checks any waiters. f must be write-locked.
+func (f *FakeClock) setTimeLocked(t time.Time) {
+ f.time = t
+ newWaiters := make([]fakeClockWaiter, 0, len(f.waiters))
+ for i := range f.waiters {
+ w := &f.waiters[i]
+ if !w.targetTime.After(t) {
+
+ if w.skipIfBlocked {
+ select {
+ case w.destChan <- t:
+ default:
+ }
+ } else {
+ w.destChan <- t
+ }
+
+ if w.stepInterval > 0 {
+ for !w.targetTime.After(t) {
+ w.targetTime = w.targetTime.Add(w.stepInterval)
+ }
+ newWaiters = append(newWaiters, *w)
+ }
+
+ } else {
+ newWaiters = append(newWaiters, f.waiters[i])
+ }
+ }
+ f.waiters = newWaiters
+}
+
+// Returns true if After has been called on f but not yet satisfied (so you can
+// write race-free tests).
+func (f *FakeClock) HasWaiters() bool {
+ f.lock.RLock()
+ defer f.lock.RUnlock()
+ return len(f.waiters) > 0
+}
+
+func (f *FakeClock) Sleep(d time.Duration) {
+ f.Step(d)
+}
+
+// IntervalClock implements Clock, but each invocation of Now steps the clock forward the specified duration
+type IntervalClock struct {
+ Time time.Time
+ Duration time.Duration
+}
+
+// Now returns i's time.
+func (i *IntervalClock) Now() time.Time {
+ i.Time = i.Time.Add(i.Duration)
+ return i.Time
+}
+
+// Since returns time since the time in i.
+func (i *IntervalClock) Since(ts time.Time) time.Duration {
+ return i.Time.Sub(ts)
+}
+
+// Unimplemented, will panic.
+// TODO: make interval clock use FakeClock so this can be implemented.
+func (*IntervalClock) After(d time.Duration) <-chan time.Time {
+ panic("IntervalClock doesn't implement After")
+}
+
+// Unimplemented, will panic.
+// TODO: make interval clock use FakeClock so this can be implemented.
+func (*IntervalClock) Tick(d time.Duration) <-chan time.Time {
+ panic("IntervalClock doesn't implement Tick")
+}
+
+func (*IntervalClock) Sleep(d time.Duration) {
+ panic("IntervalClock doesn't implement Sleep")
+}
diff --git a/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/crypto/crypto.go b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/crypto/crypto.go
new file mode 100644
index 0000000..b573c8a
--- /dev/null
+++ b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/crypto/crypto.go
@@ -0,0 +1,190 @@
+/*
+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 crypto
+
+import (
+ "bytes"
+ "crypto/rand"
+ "crypto/rsa"
+ "crypto/x509"
+ "crypto/x509/pkix"
+ "encoding/pem"
+ "errors"
+ "fmt"
+ "io/ioutil"
+ "math/big"
+ "net"
+ "os"
+ "path/filepath"
+ "time"
+)
+
+// ShouldGenSelfSignedCerts returns false if the certificate or key files already exists,
+// otherwise returns true.
+func ShouldGenSelfSignedCerts(certPath, keyPath string) bool {
+ if canReadFile(certPath) || canReadFile(keyPath) {
+ return false
+ }
+
+ return true
+}
+
+// If the file represented by path exists and
+// readable, returns true otherwise returns false.
+func canReadFile(path string) bool {
+ f, err := os.Open(path)
+ if err != nil {
+ return false
+ }
+
+ defer f.Close()
+
+ return true
+}
+
+// GenerateSelfSignedCert creates a self-signed certificate and key for the given host.
+// Host may be an IP or a DNS name
+// You may also specify additional subject alt names (either ip or dns names) for the certificate
+// The certificate will be created with file mode 0644. The key will be created with file mode 0600.
+// If the certificate or key files already exist, they will be overwritten.
+// Any parent directories of the certPath or keyPath will be created as needed with file mode 0755.
+func GenerateSelfSignedCert(host, certPath, keyPath string, alternateIPs []net.IP, alternateDNS []string) error {
+ priv, err := rsa.GenerateKey(rand.Reader, 2048)
+ if err != nil {
+ return err
+ }
+
+ template := x509.Certificate{
+ SerialNumber: big.NewInt(1),
+ Subject: pkix.Name{
+ CommonName: fmt.Sprintf("%s@%d", host, time.Now().Unix()),
+ },
+ NotBefore: time.Now(),
+ NotAfter: time.Now().Add(time.Hour * 24 * 365),
+
+ KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
+ ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
+ BasicConstraintsValid: true,
+ IsCA: true,
+ }
+
+ if ip := net.ParseIP(host); ip != nil {
+ template.IPAddresses = append(template.IPAddresses, ip)
+ } else {
+ template.DNSNames = append(template.DNSNames, host)
+ }
+
+ template.IPAddresses = append(template.IPAddresses, alternateIPs...)
+ template.DNSNames = append(template.DNSNames, alternateDNS...)
+
+ derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv)
+ if err != nil {
+ return err
+ }
+
+ // Generate cert
+ certBuffer := bytes.Buffer{}
+ if err := pem.Encode(&certBuffer, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}); err != nil {
+ return err
+ }
+
+ // Generate key
+ keyBuffer := bytes.Buffer{}
+ if err := pem.Encode(&keyBuffer, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(priv)}); err != nil {
+ return err
+ }
+
+ // Write cert
+ if err := os.MkdirAll(filepath.Dir(certPath), os.FileMode(0755)); err != nil {
+ return err
+ }
+ if err := ioutil.WriteFile(certPath, certBuffer.Bytes(), os.FileMode(0644)); err != nil {
+ return err
+ }
+
+ // Write key
+ if err := os.MkdirAll(filepath.Dir(keyPath), os.FileMode(0755)); err != nil {
+ return err
+ }
+ if err := ioutil.WriteFile(keyPath, keyBuffer.Bytes(), os.FileMode(0600)); err != nil {
+ return err
+ }
+
+ return nil
+}
+
+// CertPoolFromFile returns an x509.CertPool containing the certificates in the given PEM-encoded file.
+// Returns an error if the file could not be read, a certificate could not be parsed, or if the file does not contain any certificates
+func CertPoolFromFile(filename string) (*x509.CertPool, error) {
+ certs, err := certificatesFromFile(filename)
+ if err != nil {
+ return nil, err
+ }
+ pool := x509.NewCertPool()
+ for _, cert := range certs {
+ pool.AddCert(cert)
+ }
+ return pool, nil
+}
+
+// certificatesFromFile returns the x509.Certificates contained in the given PEM-encoded file.
+// Returns an error if the file could not be read, a certificate could not be parsed, or if the file does not contain any certificates
+func certificatesFromFile(file string) ([]*x509.Certificate, error) {
+ if len(file) == 0 {
+ return nil, errors.New("error reading certificates from an empty filename")
+ }
+ pemBlock, err := ioutil.ReadFile(file)
+ if err != nil {
+ return nil, err
+ }
+ certs, err := CertsFromPEM(pemBlock)
+ if err != nil {
+ return nil, fmt.Errorf("error reading %s: %s", file, err)
+ }
+ return certs, nil
+}
+
+// CertsFromPEM returns the x509.Certificates contained in the given PEM-encoded byte array
+// Returns an error if a certificate could not be parsed, or if the data does not contain any certificates
+func CertsFromPEM(pemCerts []byte) ([]*x509.Certificate, error) {
+ ok := false
+ certs := []*x509.Certificate{}
+ for len(pemCerts) > 0 {
+ var block *pem.Block
+ block, pemCerts = pem.Decode(pemCerts)
+ if block == nil {
+ break
+ }
+ // Only use PEM "CERTIFICATE" blocks without extra headers
+ if block.Type != "CERTIFICATE" || len(block.Headers) != 0 {
+ continue
+ }
+
+ cert, err := x509.ParseCertificate(block.Bytes)
+ if err != nil {
+ return certs, err
+ }
+
+ certs = append(certs, cert)
+ ok = true
+ }
+
+ if !ok {
+ return certs, errors.New("could not read any certificates")
+ }
+ return certs, nil
+}
diff --git a/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/doc.go b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/doc.go
new file mode 100644
index 0000000..1747db5
--- /dev/null
+++ b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/doc.go
@@ -0,0 +1,20 @@
+/*
+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 util implements various utility functions used in both testing and implementation
+// of Kubernetes. Package util may not depend on any other package in the Kubernetes
+// package tree.
+package util
diff --git a/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/errors/doc.go b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/errors/doc.go
new file mode 100644
index 0000000..b3b39bc
--- /dev/null
+++ b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/errors/doc.go
@@ -0,0 +1,18 @@
+/*
+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 errors implements various utility functions and types around errors.
+package errors
diff --git a/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/errors/errors.go b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/errors/errors.go
new file mode 100644
index 0000000..0445c14
--- /dev/null
+++ b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/errors/errors.go
@@ -0,0 +1,156 @@
+/*
+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 errors
+
+import (
+ "errors"
+ "fmt"
+)
+
+// Aggregate represents an object that contains multiple errors, but does not
+// necessarily have singular semantic meaning.
+type Aggregate interface {
+ error
+ Errors() []error
+}
+
+// NewAggregate converts a slice of errors into an Aggregate interface, which
+// is itself an implementation of the error interface. If the slice is empty,
+// this returns nil.
+func NewAggregate(errlist []error) Aggregate {
+ if len(errlist) == 0 {
+ return nil
+ }
+ return aggregate(errlist)
+}
+
+// This helper implements the error and Errors interfaces. Keeping it private
+// prevents people from making an aggregate of 0 errors, which is not
+// an error, but does satisfy the error interface.
+type aggregate []error
+
+// Error is part of the error interface.
+func (agg aggregate) Error() string {
+ if len(agg) == 0 {
+ // This should never happen, really.
+ return ""
+ }
+ if len(agg) == 1 {
+ return agg[0].Error()
+ }
+ result := fmt.Sprintf("[%s", agg[0].Error())
+ for i := 1; i < len(agg); i++ {
+ result += fmt.Sprintf(", %s", agg[i].Error())
+ }
+ result += "]"
+ return result
+}
+
+// Errors is part of the Aggregate interface.
+func (agg aggregate) Errors() []error {
+ return []error(agg)
+}
+
+// Matcher is used to match errors. Returns true if the error matches.
+type Matcher func(error) bool
+
+// FilterOut removes all errors that match any of the matchers from the input
+// error. If the input is a singular error, only that error is tested. If the
+// input implements the Aggregate interface, the list of errors will be
+// processed recursively.
+//
+// This can be used, for example, to remove known-OK errors (such as io.EOF or
+// os.PathNotFound) from a list of errors.
+func FilterOut(err error, fns ...Matcher) error {
+ if err == nil {
+ return nil
+ }
+ if agg, ok := err.(Aggregate); ok {
+ return NewAggregate(filterErrors(agg.Errors(), fns...))
+ }
+ if !matchesError(err, fns...) {
+ return err
+ }
+ return nil
+}
+
+// matchesError returns true if any Matcher returns true
+func matchesError(err error, fns ...Matcher) bool {
+ for _, fn := range fns {
+ if fn(err) {
+ return true
+ }
+ }
+ return false
+}
+
+// filterErrors returns any errors (or nested errors, if the list contains
+// nested Errors) for which all fns return false. If no errors
+// remain a nil list is returned. The resulting silec will have all
+// nested slices flattened as a side effect.
+func filterErrors(list []error, fns ...Matcher) []error {
+ result := []error{}
+ for _, err := range list {
+ r := FilterOut(err, fns...)
+ if r != nil {
+ result = append(result, r)
+ }
+ }
+ return result
+}
+
+// Flatten takes an Aggregate, which may hold other Aggregates in arbitrary
+// nesting, and flattens them all into a single Aggregate, recursively.
+func Flatten(agg Aggregate) Aggregate {
+ result := []error{}
+ if agg == nil {
+ return nil
+ }
+ for _, err := range agg.Errors() {
+ if a, ok := err.(Aggregate); ok {
+ r := Flatten(a)
+ if r != nil {
+ result = append(result, r.Errors()...)
+ }
+ } else {
+ if err != nil {
+ result = append(result, err)
+ }
+ }
+ }
+ return NewAggregate(result)
+}
+
+// AggregateGoroutines runs the provided functions in parallel, stuffing all
+// non-nil errors into the returned Aggregate.
+// Returns nil if all the functions complete successfully.
+func AggregateGoroutines(funcs ...func() error) Aggregate {
+ errChan := make(chan error, len(funcs))
+ for _, f := range funcs {
+ go func(f func() error) { errChan <- f() }(f)
+ }
+ errs := make([]error, 0)
+ for i := 0; i < cap(errChan); i++ {
+ if err := <-errChan; err != nil {
+ errs = append(errs, err)
+ }
+ }
+ return NewAggregate(errs)
+}
+
+// ErrPreconditionViolated is returned when the precondition is violated
+var ErrPreconditionViolated = errors.New("precondition is violated")
diff --git a/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/flowcontrol/backoff.go b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/flowcontrol/backoff.go
new file mode 100644
index 0000000..59b9976
--- /dev/null
+++ b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/flowcontrol/backoff.go
@@ -0,0 +1,149 @@
+/*
+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 flowcontrol
+
+import (
+ "sync"
+ "time"
+
+ "k8s.io/kubernetes/pkg/util"
+ "k8s.io/kubernetes/pkg/util/integer"
+)
+
+type backoffEntry struct {
+ backoff time.Duration
+ lastUpdate time.Time
+}
+
+type Backoff struct {
+ sync.Mutex
+ Clock util.Clock
+ defaultDuration time.Duration
+ maxDuration time.Duration
+ perItemBackoff map[string]*backoffEntry
+}
+
+func NewFakeBackOff(initial, max time.Duration, tc *util.FakeClock) *Backoff {
+ return &Backoff{
+ perItemBackoff: map[string]*backoffEntry{},
+ Clock: tc,
+ defaultDuration: initial,
+ maxDuration: max,
+ }
+}
+
+func NewBackOff(initial, max time.Duration) *Backoff {
+ return &Backoff{
+ perItemBackoff: map[string]*backoffEntry{},
+ Clock: util.RealClock{},
+ defaultDuration: initial,
+ maxDuration: max,
+ }
+}
+
+// Get the current backoff Duration
+func (p *Backoff) Get(id string) time.Duration {
+ p.Lock()
+ defer p.Unlock()
+ var delay time.Duration
+ entry, ok := p.perItemBackoff[id]
+ if ok {
+ delay = entry.backoff
+ }
+ return delay
+}
+
+// move backoff to the next mark, capping at maxDuration
+func (p *Backoff) Next(id string, eventTime time.Time) {
+ p.Lock()
+ defer p.Unlock()
+ entry, ok := p.perItemBackoff[id]
+ if !ok || hasExpired(eventTime, entry.lastUpdate, p.maxDuration) {
+ entry = p.initEntryUnsafe(id)
+ } else {
+ delay := entry.backoff * 2 // exponential
+ entry.backoff = time.Duration(integer.Int64Min(int64(delay), int64(p.maxDuration)))
+ }
+ entry.lastUpdate = p.Clock.Now()
+}
+
+// Reset forces clearing of all backoff data for a given key.
+func (p *Backoff) Reset(id string) {
+ p.Lock()
+ defer p.Unlock()
+ delete(p.perItemBackoff, id)
+}
+
+// Returns True if the elapsed time since eventTime is smaller than the current backoff window
+func (p *Backoff) IsInBackOffSince(id string, eventTime time.Time) bool {
+ p.Lock()
+ defer p.Unlock()
+ entry, ok := p.perItemBackoff[id]
+ if !ok {
+ return false
+ }
+ if hasExpired(eventTime, entry.lastUpdate, p.maxDuration) {
+ return false
+ }
+ return p.Clock.Now().Sub(eventTime) < entry.backoff
+}
+
+// Returns True if time since lastupdate is less than the current backoff window.
+func (p *Backoff) IsInBackOffSinceUpdate(id string, eventTime time.Time) bool {
+ p.Lock()
+ defer p.Unlock()
+ entry, ok := p.perItemBackoff[id]
+ if !ok {
+ return false
+ }
+ if hasExpired(eventTime, entry.lastUpdate, p.maxDuration) {
+ return false
+ }
+ return eventTime.Sub(entry.lastUpdate) < entry.backoff
+}
+
+// Garbage collect records that have aged past maxDuration. Backoff users are expected
+// to invoke this periodically.
+func (p *Backoff) GC() {
+ p.Lock()
+ defer p.Unlock()
+ now := p.Clock.Now()
+ for id, entry := range p.perItemBackoff {
+ if now.Sub(entry.lastUpdate) > p.maxDuration*2 {
+ // GC when entry has not been updated for 2*maxDuration
+ delete(p.perItemBackoff, id)
+ }
+ }
+}
+
+func (p *Backoff) DeleteEntry(id string) {
+ p.Lock()
+ defer p.Unlock()
+ delete(p.perItemBackoff, id)
+}
+
+// Take a lock on *Backoff, before calling initEntryUnsafe
+func (p *Backoff) initEntryUnsafe(id string) *backoffEntry {
+ entry := &backoffEntry{backoff: p.defaultDuration}
+ p.perItemBackoff[id] = entry
+ return entry
+}
+
+// After 2*maxDuration we restart the backoff factor to the beginning
+func hasExpired(eventTime time.Time, lastUpdate time.Time, maxDuration time.Duration) bool {
+ return eventTime.Sub(lastUpdate) > maxDuration*2 // consider stable if it's ok for twice the maxDuration
+}
diff --git a/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/flowcontrol/throttle.go b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/flowcontrol/throttle.go
new file mode 100644
index 0000000..482ba7d
--- /dev/null
+++ b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/flowcontrol/throttle.go
@@ -0,0 +1,116 @@
+/*
+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 flowcontrol
+
+import (
+ "sync"
+
+ "github.com/juju/ratelimit"
+)
+
+type RateLimiter interface {
+ // TryAccept returns true if a token is taken immediately. Otherwise,
+ // it returns false.
+ TryAccept() bool
+ // Accept returns once a token becomes available.
+ Accept()
+ // Stop stops the rate limiter, subsequent calls to CanAccept will return false
+ Stop()
+ // Saturation returns a percentage number which describes how saturated
+ // this rate limiter is.
+ // Usually we use token bucket rate limiter. In that case,
+ // 1.0 means no tokens are available; 0.0 means we have a full bucket of tokens to use.
+ Saturation() float64
+}
+
+type tokenBucketRateLimiter struct {
+ limiter *ratelimit.Bucket
+}
+
+// NewTokenBucketRateLimiter creates a rate limiter which implements a token bucket approach.
+// The rate limiter allows bursts of up to 'burst' to exceed the QPS, while still maintaining a
+// smoothed qps rate of 'qps'.
+// The bucket is initially filled with 'burst' tokens, and refills at a rate of 'qps'.
+// The maximum number of tokens in the bucket is capped at 'burst'.
+func NewTokenBucketRateLimiter(qps float32, burst int) RateLimiter {
+ limiter := ratelimit.NewBucketWithRate(float64(qps), int64(burst))
+ return &tokenBucketRateLimiter{limiter}
+}
+
+func (t *tokenBucketRateLimiter) TryAccept() bool {
+ return t.limiter.TakeAvailable(1) == 1
+}
+
+func (t *tokenBucketRateLimiter) Saturation() float64 {
+ capacity := t.limiter.Capacity()
+ avail := t.limiter.Available()
+ return float64(capacity-avail) / float64(capacity)
+}
+
+// Accept will block until a token becomes available
+func (t *tokenBucketRateLimiter) Accept() {
+ t.limiter.Wait(1)
+}
+
+func (t *tokenBucketRateLimiter) Stop() {
+}
+
+type fakeAlwaysRateLimiter struct{}
+
+func NewFakeAlwaysRateLimiter() RateLimiter {
+ return &fakeAlwaysRateLimiter{}
+}
+
+func (t *fakeAlwaysRateLimiter) TryAccept() bool {
+ return true
+}
+
+func (t *fakeAlwaysRateLimiter) Saturation() float64 {
+ return 0
+}
+
+func (t *fakeAlwaysRateLimiter) Stop() {}
+
+func (t *fakeAlwaysRateLimiter) Accept() {}
+
+type fakeNeverRateLimiter struct {
+ wg sync.WaitGroup
+}
+
+func NewFakeNeverRateLimiter() RateLimiter {
+ wg := sync.WaitGroup{}
+ wg.Add(1)
+ return &fakeNeverRateLimiter{
+ wg: wg,
+ }
+}
+
+func (t *fakeNeverRateLimiter) TryAccept() bool {
+ return false
+}
+
+func (t *fakeNeverRateLimiter) Saturation() float64 {
+ return 1
+}
+
+func (t *fakeNeverRateLimiter) Stop() {
+ t.wg.Done()
+}
+
+func (t *fakeNeverRateLimiter) Accept() {
+ t.wg.Wait()
+}
diff --git a/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/framer/framer.go b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/framer/framer.go
new file mode 100644
index 0000000..066680f
--- /dev/null
+++ b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/framer/framer.go
@@ -0,0 +1,167 @@
+/*
+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 framer implements simple frame decoding techniques for an io.ReadCloser
+package framer
+
+import (
+ "encoding/binary"
+ "encoding/json"
+ "io"
+)
+
+type lengthDelimitedFrameWriter struct {
+ w io.Writer
+ h [4]byte
+}
+
+func NewLengthDelimitedFrameWriter(w io.Writer) io.Writer {
+ return &lengthDelimitedFrameWriter{w: w}
+}
+
+// Write writes a single frame to the nested writer, prepending it with the length in
+// in bytes of data (as a 4 byte, bigendian uint32).
+func (w *lengthDelimitedFrameWriter) Write(data []byte) (int, error) {
+ binary.BigEndian.PutUint32(w.h[:], uint32(len(data)))
+ n, err := w.w.Write(w.h[:])
+ if err != nil {
+ return 0, err
+ }
+ if n != len(w.h) {
+ return 0, io.ErrShortWrite
+ }
+ return w.w.Write(data)
+}
+
+type lengthDelimitedFrameReader struct {
+ r io.ReadCloser
+ remaining int
+}
+
+// NewLengthDelimitedFrameReader returns an io.Reader that will decode length-prefixed
+// frames off of a stream.
+//
+// The protocol is:
+//
+// stream: message ...
+// message: prefix body
+// prefix: 4 byte uint32 in BigEndian order, denotes length of body
+// body: bytes (0..prefix)
+//
+// If the buffer passed to Read is not long enough to contain an entire frame, io.ErrShortRead
+// will be returned along with the number of bytes read.
+func NewLengthDelimitedFrameReader(r io.ReadCloser) io.ReadCloser {
+ return &lengthDelimitedFrameReader{r: r}
+}
+
+// Read attempts to read an entire frame into data. If that is not possible, io.ErrShortBuffer
+// is returned and subsequent calls will attempt to read the last frame. A frame is complete when
+// err is nil.
+func (r *lengthDelimitedFrameReader) Read(data []byte) (int, error) {
+ if r.remaining <= 0 {
+ header := [4]byte{}
+ n, err := io.ReadAtLeast(r.r, header[:4], 4)
+ if err != nil {
+ return 0, err
+ }
+ if n != 4 {
+ return 0, io.ErrUnexpectedEOF
+ }
+ frameLength := int(binary.BigEndian.Uint32(header[:]))
+ r.remaining = frameLength
+ }
+
+ expect := r.remaining
+ max := expect
+ if max > len(data) {
+ max = len(data)
+ }
+ n, err := io.ReadAtLeast(r.r, data[:max], int(max))
+ r.remaining -= n
+ if err == io.ErrShortBuffer || r.remaining > 0 {
+ return n, io.ErrShortBuffer
+ }
+ if err != nil {
+ return n, err
+ }
+ if n != expect {
+ return n, io.ErrUnexpectedEOF
+ }
+
+ return n, nil
+}
+
+func (r *lengthDelimitedFrameReader) Close() error {
+ return r.r.Close()
+}
+
+type jsonFrameReader struct {
+ r io.ReadCloser
+ decoder *json.Decoder
+ remaining []byte
+}
+
+// NewJSONFramedReader returns an io.Reader that will decode individual JSON objects off
+// of a wire.
+//
+// The boundaries between each frame are valid JSON objects. A JSON parsing error will terminate
+// the read.
+func NewJSONFramedReader(r io.ReadCloser) io.ReadCloser {
+ return &jsonFrameReader{
+ r: r,
+ decoder: json.NewDecoder(r),
+ }
+}
+
+// ReadFrame decodes the next JSON object in the stream, or returns an error. The returned
+// byte slice will be modified the next time ReadFrame is invoked and should not be altered.
+func (r *jsonFrameReader) Read(data []byte) (int, error) {
+ // Return whatever remaining data exists from an in progress frame
+ if n := len(r.remaining); n > 0 {
+ if n <= len(data) {
+ data = append(data[0:0], r.remaining...)
+ r.remaining = nil
+ return n, nil
+ }
+
+ n = len(data)
+ data = append(data[0:0], r.remaining[:n]...)
+ r.remaining = r.remaining[n:]
+ return n, io.ErrShortBuffer
+ }
+
+ // RawMessage#Unmarshal appends to data - we reset the slice down to 0 and will either see
+ // data written to data, or be larger than data and a different array.
+ n := len(data)
+ m := json.RawMessage(data[:0])
+ if err := r.decoder.Decode(&m); err != nil {
+ return 0, err
+ }
+
+ // If capacity of data is less than length of the message, decoder will allocate a new slice
+ // and set m to it, which means we need to copy the partial result back into data and preserve
+ // the remaining result for subsequent reads.
+ if len(m) > n {
+ data = append(data[0:0], m[:n]...)
+ r.remaining = m[n:]
+ return n, io.ErrShortBuffer
+ }
+ return len(m), nil
+}
+
+func (r *jsonFrameReader) Close() error {
+ return r.r.Close()
+}
diff --git a/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/hash/hash.go b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/hash/hash.go
new file mode 100644
index 0000000..803f066
--- /dev/null
+++ b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/hash/hash.go
@@ -0,0 +1,37 @@
+/*
+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 hash
+
+import (
+ "hash"
+
+ "github.com/davecgh/go-spew/spew"
+)
+
+// DeepHashObject writes specified object to hash using the spew library
+// which follows pointers and prints actual values of the nested objects
+// ensuring the hash does not change when a pointer changes.
+func DeepHashObject(hasher hash.Hash, objectToWrite interface{}) {
+ hasher.Reset()
+ printer := spew.ConfigState{
+ Indent: " ",
+ SortKeys: true,
+ DisableMethods: true,
+ SpewKeys: true,
+ }
+ printer.Fprintf(hasher, "%#v", objectToWrite)
+}
diff --git a/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/homedir/homedir.go b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/homedir/homedir.go
new file mode 100644
index 0000000..4034754
--- /dev/null
+++ b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/homedir/homedir.go
@@ -0,0 +1,40 @@
+/*
+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 homedir
+
+import (
+ "os"
+ "runtime"
+)
+
+// HomeDir returns the home directory for the current user
+func HomeDir() string {
+ if runtime.GOOS == "windows" {
+ if homeDrive, homePath := os.Getenv("HOMEDRIVE"), os.Getenv("HOMEPATH"); len(homeDrive) > 0 && len(homePath) > 0 {
+ homeDir := homeDrive + homePath
+ if _, err := os.Stat(homeDir); err == nil {
+ return homeDir
+ }
+ }
+ if userProfile := os.Getenv("USERPROFILE"); len(userProfile) > 0 {
+ if _, err := os.Stat(userProfile); err == nil {
+ return userProfile
+ }
+ }
+ }
+ return os.Getenv("HOME")
+}
diff --git a/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/integer/integer.go b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/integer/integer.go
new file mode 100644
index 0000000..c6ea106
--- /dev/null
+++ b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/integer/integer.go
@@ -0,0 +1,67 @@
+/*
+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 integer
+
+func IntMax(a, b int) int {
+ if b > a {
+ return b
+ }
+ return a
+}
+
+func IntMin(a, b int) int {
+ if b < a {
+ return b
+ }
+ return a
+}
+
+func Int32Max(a, b int32) int32 {
+ if b > a {
+ return b
+ }
+ return a
+}
+
+func Int32Min(a, b int32) int32 {
+ if b < a {
+ return b
+ }
+ return a
+}
+
+func Int64Max(a, b int64) int64 {
+ if b > a {
+ return b
+ }
+ return a
+}
+
+func Int64Min(a, b int64) int64 {
+ if b < a {
+ return b
+ }
+ return a
+}
+
+// RoundToInt32 rounds floats into integer numbers.
+func RoundToInt32(a float64) int32 {
+ if a < 0 {
+ return int32(a - 0.5)
+ }
+ return int32(a + 0.5)
+}
diff --git a/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/intstr/generated.pb.go b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/intstr/generated.pb.go
new file mode 100644
index 0000000..3c2bf4f
--- /dev/null
+++ b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/intstr/generated.pb.go
@@ -0,0 +1,347 @@
+/*
+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/util/intstr/generated.proto
+// DO NOT EDIT!
+
+/*
+ Package intstr is a generated protocol buffer package.
+
+ It is generated from these files:
+ k8s.io/kubernetes/pkg/util/intstr/generated.proto
+
+ It has these top-level messages:
+ IntOrString
+*/
+package intstr
+
+import proto "github.com/gogo/protobuf/proto"
+import fmt "fmt"
+import math "math"
+
+import io "io"
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+func (m *IntOrString) Reset() { *m = IntOrString{} }
+func (*IntOrString) ProtoMessage() {}
+
+func init() {
+ proto.RegisterType((*IntOrString)(nil), "k8s.io.kubernetes.pkg.util.intstr.IntOrString")
+}
+func (m *IntOrString) 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 *IntOrString) MarshalTo(data []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ data[i] = 0x8
+ i++
+ i = encodeVarintGenerated(data, i, uint64(m.Type))
+ data[i] = 0x10
+ i++
+ i = encodeVarintGenerated(data, i, uint64(m.IntVal))
+ data[i] = 0x1a
+ i++
+ i = encodeVarintGenerated(data, i, uint64(len(m.StrVal)))
+ i += copy(data[i:], m.StrVal)
+ 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 *IntOrString) Size() (n int) {
+ var l int
+ _ = l
+ n += 1 + sovGenerated(uint64(m.Type))
+ n += 1 + sovGenerated(uint64(m.IntVal))
+ l = len(m.StrVal)
+ 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 (m *IntOrString) 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: IntOrString: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: IntOrString: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Type", wireType)
+ }
+ m.Type = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowGenerated
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := data[iNdEx]
+ iNdEx++
+ m.Type |= (Type(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 2:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field IntVal", wireType)
+ }
+ m.IntVal = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowGenerated
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := data[iNdEx]
+ iNdEx++
+ m.IntVal |= (int32(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 3:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field StrVal", 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.StrVal = string(data[iNdEx:postIndex])
+ 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")
+)
diff --git a/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/intstr/generated.proto b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/intstr/generated.proto
new file mode 100644
index 0000000..dd508e1
--- /dev/null
+++ b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/intstr/generated.proto
@@ -0,0 +1,42 @@
+/*
+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.util.intstr;
+
+// Package-wide variables from generator "generated".
+option go_package = "intstr";
+
+// IntOrString is a type that can hold an int32 or a string. When used in
+// JSON or YAML marshalling and unmarshalling, it produces or consumes the
+// inner type. This allows you to have, for example, a JSON field that can
+// accept a name or number.
+// TODO: Rename to Int32OrString
+//
+// +protobuf=true
+// +protobuf.options.(gogoproto.goproto_stringer)=false
+message IntOrString {
+ optional int64 type = 1;
+
+ optional int32 intVal = 2;
+
+ optional string strVal = 3;
+}
+
diff --git a/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/intstr/intstr.go b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/intstr/intstr.go
new file mode 100644
index 0000000..59e7a06
--- /dev/null
+++ b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/intstr/intstr.go
@@ -0,0 +1,147 @@
+/*
+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 intstr
+
+import (
+ "encoding/json"
+ "fmt"
+ "math"
+ "strconv"
+ "strings"
+
+ "github.com/google/gofuzz"
+)
+
+// IntOrString is a type that can hold an int32 or a string. When used in
+// JSON or YAML marshalling and unmarshalling, it produces or consumes the
+// inner type. This allows you to have, for example, a JSON field that can
+// accept a name or number.
+// TODO: Rename to Int32OrString
+//
+// +protobuf=true
+// +protobuf.options.(gogoproto.goproto_stringer)=false
+type IntOrString struct {
+ Type Type `protobuf:"varint,1,opt,name=type,casttype=Type"`
+ IntVal int32 `protobuf:"varint,2,opt,name=intVal"`
+ StrVal string `protobuf:"bytes,3,opt,name=strVal"`
+}
+
+// Type represents the stored type of IntOrString.
+type Type int
+
+const (
+ Int Type = iota // The IntOrString holds an int.
+ String // The IntOrString holds a string.
+)
+
+// FromInt creates an IntOrString object with an int32 value. It is
+// your responsibility not to call this method with a value greater
+// than int32.
+// TODO: convert to (val int32)
+func FromInt(val int) IntOrString {
+ return IntOrString{Type: Int, IntVal: int32(val)}
+}
+
+// FromString creates an IntOrString object with a string value.
+func FromString(val string) IntOrString {
+ return IntOrString{Type: String, StrVal: val}
+}
+
+// UnmarshalJSON implements the json.Unmarshaller interface.
+func (intstr *IntOrString) UnmarshalJSON(value []byte) error {
+ if value[0] == '"' {
+ intstr.Type = String
+ return json.Unmarshal(value, &intstr.StrVal)
+ }
+ intstr.Type = Int
+ return json.Unmarshal(value, &intstr.IntVal)
+}
+
+// String returns the string value, or the Itoa of the int value.
+func (intstr *IntOrString) String() string {
+ if intstr.Type == String {
+ return intstr.StrVal
+ }
+ return strconv.Itoa(intstr.IntValue())
+}
+
+// IntValue returns the IntVal if type Int, or if
+// it is a String, will attempt a conversion to int.
+func (intstr *IntOrString) IntValue() int {
+ if intstr.Type == String {
+ i, _ := strconv.Atoi(intstr.StrVal)
+ return i
+ }
+ return int(intstr.IntVal)
+}
+
+// MarshalJSON implements the json.Marshaller interface.
+func (intstr IntOrString) MarshalJSON() ([]byte, error) {
+ switch intstr.Type {
+ case Int:
+ return json.Marshal(intstr.IntVal)
+ case String:
+ return json.Marshal(intstr.StrVal)
+ default:
+ return []byte{}, fmt.Errorf("impossible IntOrString.Type")
+ }
+}
+
+func (intstr *IntOrString) Fuzz(c fuzz.Continue) {
+ if intstr == nil {
+ return
+ }
+ if c.RandBool() {
+ intstr.Type = Int
+ c.Fuzz(&intstr.IntVal)
+ intstr.StrVal = ""
+ } else {
+ intstr.Type = String
+ intstr.IntVal = 0
+ c.Fuzz(&intstr.StrVal)
+ }
+}
+
+func GetValueFromIntOrPercent(intOrPercent *IntOrString, total int, roundUp bool) (int, error) {
+ value, isPercent, err := getIntOrPercentValue(intOrPercent)
+ if err != nil {
+ return 0, fmt.Errorf("invalid value for IntOrString: %v", err)
+ }
+ if isPercent {
+ if roundUp {
+ value = int(math.Ceil(float64(value) * (float64(total)) / 100))
+ } else {
+ value = int(math.Floor(float64(value) * (float64(total)) / 100))
+ }
+ }
+ return value, nil
+}
+
+func getIntOrPercentValue(intOrStr *IntOrString) (int, bool, error) {
+ switch intOrStr.Type {
+ case Int:
+ return intOrStr.IntValue(), false, nil
+ case String:
+ s := strings.Replace(intOrStr.StrVal, "%", "", -1)
+ v, err := strconv.Atoi(s)
+ if err != nil {
+ return 0, false, fmt.Errorf("invalid value %q: %v", intOrStr.StrVal, err)
+ }
+ return int(v), true, nil
+ }
+ return 0, false, fmt.Errorf("invalid type: neither int nor percentage")
+}
diff --git a/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/json/json.go b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/json/json.go
new file mode 100644
index 0000000..e8054a1
--- /dev/null
+++ b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/json/json.go
@@ -0,0 +1,107 @@
+/*
+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 json
+
+import (
+ "bytes"
+ "encoding/json"
+ "io"
+)
+
+// NewEncoder delegates to json.NewEncoder
+// It is only here so this package can be a drop-in for common encoding/json uses
+func NewEncoder(w io.Writer) *json.Encoder {
+ return json.NewEncoder(w)
+}
+
+// Marshal delegates to json.Marshal
+// It is only here so this package can be a drop-in for common encoding/json uses
+func Marshal(v interface{}) ([]byte, error) {
+ return json.Marshal(v)
+}
+
+// Unmarshal unmarshals the given data
+// If v is a *map[string]interface{}, numbers are converted to int64 or float64
+func Unmarshal(data []byte, v interface{}) error {
+ switch v := v.(type) {
+ case *map[string]interface{}:
+ // Build a decoder from the given data
+ decoder := json.NewDecoder(bytes.NewBuffer(data))
+ // Preserve numbers, rather than casting to float64 automatically
+ decoder.UseNumber()
+ // Run the decode
+ if err := decoder.Decode(v); err != nil {
+ return err
+ }
+ // If the decode succeeds, post-process the map to convert json.Number objects to int64 or float64
+ return convertMapNumbers(*v)
+
+ default:
+ return json.Unmarshal(data, v)
+ }
+}
+
+// convertMapNumbers traverses the map, converting any json.Number values to int64 or float64.
+// values which are map[string]interface{} or []interface{} are recursively visited
+func convertMapNumbers(m map[string]interface{}) error {
+ var err error
+ for k, v := range m {
+ switch v := v.(type) {
+ case json.Number:
+ m[k], err = convertNumber(v)
+ case map[string]interface{}:
+ err = convertMapNumbers(v)
+ case []interface{}:
+ err = convertSliceNumbers(v)
+ }
+ if err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+// convertSliceNumbers traverses the slice, converting any json.Number values to int64 or float64.
+// values which are map[string]interface{} or []interface{} are recursively visited
+func convertSliceNumbers(s []interface{}) error {
+ var err error
+ for i, v := range s {
+ switch v := v.(type) {
+ case json.Number:
+ s[i], err = convertNumber(v)
+ case map[string]interface{}:
+ err = convertMapNumbers(v)
+ case []interface{}:
+ err = convertSliceNumbers(v)
+ }
+ if err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+// convertNumber converts a json.Number to an int64 or float64, or returns an error
+func convertNumber(n json.Number) (interface{}, error) {
+ // Attempt to convert to an int64 first
+ if i, err := n.Int64(); err == nil {
+ return i, nil
+ }
+ // Return a float64 (default json.Decode() behavior)
+ // An overflow will return an error
+ return n.Float64()
+}
diff --git a/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/line_delimiter.go b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/line_delimiter.go
new file mode 100644
index 0000000..9f64260
--- /dev/null
+++ b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/line_delimiter.go
@@ -0,0 +1,63 @@
+/*
+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 util
+
+import (
+ "bytes"
+ "io"
+ "strings"
+)
+
+// A Line Delimiter is a filter that will
+type LineDelimiter struct {
+ output io.Writer
+ delimiter []byte
+ buf bytes.Buffer
+}
+
+// NewLineDelimiter allocates a new io.Writer that will split input on lines
+// and bracket each line with the delimiter string. This can be useful in
+// output tests where it is difficult to see and test trailing whitespace.
+func NewLineDelimiter(output io.Writer, delimiter string) *LineDelimiter {
+ return &LineDelimiter{output: output, delimiter: []byte(delimiter)}
+}
+
+// Write writes buf to the LineDelimiter ld. The only errors returned are ones
+// encountered while writing to the underlying output stream.
+func (ld *LineDelimiter) Write(buf []byte) (n int, err error) {
+ return ld.buf.Write(buf)
+}
+
+// Flush all lines up until now. This will assume insert a linebreak at the current point of the stream.
+func (ld *LineDelimiter) Flush() (err error) {
+ lines := strings.Split(ld.buf.String(), "\n")
+ for _, line := range lines {
+ if _, err = ld.output.Write(ld.delimiter); err != nil {
+ return
+ }
+ if _, err = ld.output.Write([]byte(line)); err != nil {
+ return
+ }
+ if _, err = ld.output.Write(ld.delimiter); err != nil {
+ return
+ }
+ if _, err = ld.output.Write([]byte("\n")); err != nil {
+ return
+ }
+ }
+ return
+}
diff --git a/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/logs.go b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/logs.go
new file mode 100644
index 0000000..ea27f48
--- /dev/null
+++ b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/logs.go
@@ -0,0 +1,61 @@
+/*
+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 util
+
+import (
+ "flag"
+ "log"
+ "time"
+
+ "github.com/golang/glog"
+ "github.com/spf13/pflag"
+ "k8s.io/kubernetes/pkg/util/wait"
+)
+
+var logFlushFreq = pflag.Duration("log-flush-frequency", 5*time.Second, "Maximum number of seconds between log flushes")
+
+// TODO(thockin): This is temporary until we agree on log dirs and put those into each cmd.
+func init() {
+ flag.Set("logtostderr", "true")
+}
+
+// GlogWriter serves as a bridge between the standard log package and the glog package.
+type GlogWriter struct{}
+
+// Write implements the io.Writer interface.
+func (writer GlogWriter) Write(data []byte) (n int, err error) {
+ glog.Info(string(data))
+ return len(data), nil
+}
+
+// InitLogs initializes logs the way we want for kubernetes.
+func InitLogs() {
+ log.SetOutput(GlogWriter{})
+ log.SetFlags(0)
+ // The default glog flush interval is 30 seconds, which is frighteningly long.
+ go wait.Until(glog.Flush, *logFlushFreq, wait.NeverStop)
+}
+
+// FlushLogs flushes logs immediately.
+func FlushLogs() {
+ glog.Flush()
+}
+
+// NewLogger creates a new log.Logger which sends logs to glog.Info.
+func NewLogger(prefix string) *log.Logger {
+ return log.New(GlogWriter{}, prefix, 0)
+}
diff --git a/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/net/http.go b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/net/http.go
new file mode 100644
index 0000000..582fb9a
--- /dev/null
+++ b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/net/http.go
@@ -0,0 +1,235 @@
+/*
+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 net
+
+import (
+ "crypto/tls"
+ "fmt"
+ "io"
+ "net"
+ "net/http"
+ "net/url"
+ "os"
+ "strconv"
+ "strings"
+
+ "github.com/golang/glog"
+ "golang.org/x/net/http2"
+)
+
+// IsProbableEOF returns true if the given error resembles a connection termination
+// scenario that would justify assuming that the watch is empty.
+// These errors are what the Go http stack returns back to us which are general
+// connection closure errors (strongly correlated) and callers that need to
+// differentiate probable errors in connection behavior between normal "this is
+// disconnected" should use the method.
+func IsProbableEOF(err error) bool {
+ if uerr, ok := err.(*url.Error); ok {
+ err = uerr.Err
+ }
+ switch {
+ case err == io.EOF:
+ return true
+ case err.Error() == "http: can't write HTTP request on broken connection":
+ return true
+ case strings.Contains(err.Error(), "connection reset by peer"):
+ return true
+ case strings.Contains(strings.ToLower(err.Error()), "use of closed network connection"):
+ return true
+ }
+ return false
+}
+
+var defaultTransport = http.DefaultTransport.(*http.Transport)
+
+// SetOldTransportDefaults applies the defaults from http.DefaultTransport
+// for the Proxy, Dial, and TLSHandshakeTimeout fields if unset
+func SetOldTransportDefaults(t *http.Transport) *http.Transport {
+ if t.Proxy == nil || isDefault(t.Proxy) {
+ // http.ProxyFromEnvironment doesn't respect CIDRs and that makes it impossible to exclude things like pod and service IPs from proxy settings
+ // ProxierWithNoProxyCIDR allows CIDR rules in NO_PROXY
+ t.Proxy = NewProxierWithNoProxyCIDR(http.ProxyFromEnvironment)
+ }
+ if t.Dial == nil {
+ t.Dial = defaultTransport.Dial
+ }
+ if t.TLSHandshakeTimeout == 0 {
+ t.TLSHandshakeTimeout = defaultTransport.TLSHandshakeTimeout
+ }
+ return t
+}
+
+// SetTransportDefaults applies the defaults from http.DefaultTransport
+// for the Proxy, Dial, and TLSHandshakeTimeout fields if unset
+func SetTransportDefaults(t *http.Transport) *http.Transport {
+ t = SetOldTransportDefaults(t)
+ // Allow clients to disable http2 if needed.
+ if s := os.Getenv("DISABLE_HTTP2"); len(s) > 0 {
+ glog.Infof("HTTP2 has been explicitly disabled")
+ } else {
+ if err := http2.ConfigureTransport(t); err != nil {
+ glog.Warningf("Transport failed http2 configuration: %v", err)
+ }
+ }
+ return t
+}
+
+type RoundTripperWrapper interface {
+ http.RoundTripper
+ WrappedRoundTripper() http.RoundTripper
+}
+
+type DialFunc func(net, addr string) (net.Conn, error)
+
+func Dialer(transport http.RoundTripper) (DialFunc, error) {
+ if transport == nil {
+ return nil, nil
+ }
+
+ switch transport := transport.(type) {
+ case *http.Transport:
+ return transport.Dial, nil
+ case RoundTripperWrapper:
+ return Dialer(transport.WrappedRoundTripper())
+ default:
+ return nil, fmt.Errorf("unknown transport type: %v", transport)
+ }
+}
+
+func TLSClientConfig(transport http.RoundTripper) (*tls.Config, error) {
+ if transport == nil {
+ return nil, nil
+ }
+
+ switch transport := transport.(type) {
+ case *http.Transport:
+ return transport.TLSClientConfig, nil
+ case RoundTripperWrapper:
+ return TLSClientConfig(transport.WrappedRoundTripper())
+ default:
+ return nil, fmt.Errorf("unknown transport type: %v", transport)
+ }
+}
+
+func FormatURL(scheme string, host string, port int, path string) *url.URL {
+ return &url.URL{
+ Scheme: scheme,
+ Host: net.JoinHostPort(host, strconv.Itoa(port)),
+ Path: path,
+ }
+}
+
+func GetHTTPClient(req *http.Request) string {
+ if userAgent, ok := req.Header["User-Agent"]; ok {
+ if len(userAgent) > 0 {
+ return userAgent[0]
+ }
+ }
+ return "unknown"
+}
+
+// Extracts and returns the clients IP from the given request.
+// Looks at X-Forwarded-For header, X-Real-Ip header and request.RemoteAddr in that order.
+// Returns nil if none of them are set or is set to an invalid value.
+func GetClientIP(req *http.Request) net.IP {
+ hdr := req.Header
+ // First check the X-Forwarded-For header for requests via proxy.
+ hdrForwardedFor := hdr.Get("X-Forwarded-For")
+ if hdrForwardedFor != "" {
+ // X-Forwarded-For can be a csv of IPs in case of multiple proxies.
+ // Use the first valid one.
+ parts := strings.Split(hdrForwardedFor, ",")
+ for _, part := range parts {
+ ip := net.ParseIP(strings.TrimSpace(part))
+ if ip != nil {
+ return ip
+ }
+ }
+ }
+
+ // Try the X-Real-Ip header.
+ hdrRealIp := hdr.Get("X-Real-Ip")
+ if hdrRealIp != "" {
+ ip := net.ParseIP(hdrRealIp)
+ if ip != nil {
+ return ip
+ }
+ }
+
+ // Fallback to Remote Address in request, which will give the correct client IP when there is no proxy.
+ // Remote Address in Go's HTTP server is in the form host:port so we need to split that first.
+ host, _, err := net.SplitHostPort(req.RemoteAddr)
+ if err == nil {
+ return net.ParseIP(host)
+ }
+
+ // Fallback if Remote Address was just IP.
+ return net.ParseIP(req.RemoteAddr)
+}
+
+var defaultProxyFuncPointer = fmt.Sprintf("%p", http.ProxyFromEnvironment)
+
+// isDefault checks to see if the transportProxierFunc is pointing to the default one
+func isDefault(transportProxier func(*http.Request) (*url.URL, error)) bool {
+ transportProxierPointer := fmt.Sprintf("%p", transportProxier)
+ return transportProxierPointer == defaultProxyFuncPointer
+}
+
+// NewProxierWithNoProxyCIDR constructs a Proxier function that respects CIDRs in NO_PROXY and delegates if
+// no matching CIDRs are found
+func NewProxierWithNoProxyCIDR(delegate func(req *http.Request) (*url.URL, error)) func(req *http.Request) (*url.URL, error) {
+ // we wrap the default method, so we only need to perform our check if the NO_PROXY envvar has a CIDR in it
+ noProxyEnv := os.Getenv("NO_PROXY")
+ noProxyRules := strings.Split(noProxyEnv, ",")
+
+ cidrs := []*net.IPNet{}
+ for _, noProxyRule := range noProxyRules {
+ _, cidr, _ := net.ParseCIDR(noProxyRule)
+ if cidr != nil {
+ cidrs = append(cidrs, cidr)
+ }
+ }
+
+ if len(cidrs) == 0 {
+ return delegate
+ }
+
+ return func(req *http.Request) (*url.URL, error) {
+ host := req.URL.Host
+ // for some urls, the Host is already the host, not the host:port
+ if net.ParseIP(host) == nil {
+ var err error
+ host, _, err = net.SplitHostPort(req.URL.Host)
+ if err != nil {
+ return delegate(req)
+ }
+ }
+
+ ip := net.ParseIP(host)
+ if ip == nil {
+ return delegate(req)
+ }
+
+ for _, cidr := range cidrs {
+ if cidr.Contains(ip) {
+ return nil, nil
+ }
+ }
+
+ return delegate(req)
+ }
+}
diff --git a/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/net/interface.go b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/net/interface.go
new file mode 100644
index 0000000..a1e53d2
--- /dev/null
+++ b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/net/interface.go
@@ -0,0 +1,278 @@
+/*
+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 net
+
+import (
+ "bufio"
+ "encoding/hex"
+ "fmt"
+ "io"
+ "net"
+ "os"
+
+ "strings"
+
+ "github.com/golang/glog"
+)
+
+type Route struct {
+ Interface string
+ Destination net.IP
+ Gateway net.IP
+ // TODO: add more fields here if needed
+}
+
+func getRoutes(input io.Reader) ([]Route, error) {
+ routes := []Route{}
+ if input == nil {
+ return nil, fmt.Errorf("input is nil")
+ }
+ scanner := bufio.NewReader(input)
+ for {
+ line, err := scanner.ReadString('\n')
+ if err == io.EOF {
+ break
+ }
+ //ignore the headers in the route info
+ if strings.HasPrefix(line, "Iface") {
+ continue
+ }
+ fields := strings.Fields(line)
+ routes = append(routes, Route{})
+ route := &routes[len(routes)-1]
+ route.Interface = fields[0]
+ ip, err := parseIP(fields[1])
+ if err != nil {
+ return nil, err
+ }
+ route.Destination = ip
+ ip, err = parseIP(fields[2])
+ if err != nil {
+ return nil, err
+ }
+ route.Gateway = ip
+ }
+ return routes, nil
+}
+
+func parseIP(str string) (net.IP, error) {
+ if str == "" {
+ return nil, fmt.Errorf("input is nil")
+ }
+ bytes, err := hex.DecodeString(str)
+ if err != nil {
+ return nil, err
+ }
+ //TODO add ipv6 support
+ if len(bytes) != net.IPv4len {
+ return nil, fmt.Errorf("only IPv4 is supported")
+ }
+ bytes[0], bytes[1], bytes[2], bytes[3] = bytes[3], bytes[2], bytes[1], bytes[0]
+ return net.IP(bytes), nil
+}
+
+func isInterfaceUp(intf *net.Interface) bool {
+ if intf == nil {
+ return false
+ }
+ if intf.Flags&net.FlagUp != 0 {
+ glog.V(4).Infof("Interface %v is up", intf.Name)
+ return true
+ }
+ return false
+}
+
+//getFinalIP method receives all the IP addrs of a Interface
+//and returns a nil if the address is Loopback, Ipv6, link-local or nil.
+//It returns a valid IPv4 if an Ipv4 address is found in the array.
+func getFinalIP(addrs []net.Addr) (net.IP, error) {
+ if len(addrs) > 0 {
+ for i := range addrs {
+ glog.V(4).Infof("Checking addr %s.", addrs[i].String())
+ ip, _, err := net.ParseCIDR(addrs[i].String())
+ if err != nil {
+ return nil, err
+ }
+ //Only IPv4
+ //TODO : add IPv6 support
+ if ip.To4() != nil {
+ if !ip.IsLoopback() && !ip.IsLinkLocalMulticast() && !ip.IsLinkLocalUnicast() {
+ glog.V(4).Infof("IP found %v", ip)
+ return ip, nil
+ } else {
+ glog.V(4).Infof("Loopback/link-local found %v", ip)
+ }
+ } else {
+ glog.V(4).Infof("%v is not a valid IPv4 address", ip)
+ }
+
+ }
+ }
+ return nil, nil
+}
+
+func getIPFromInterface(intfName string, nw networkInterfacer) (net.IP, error) {
+ intf, err := nw.InterfaceByName(intfName)
+ if err != nil {
+ return nil, err
+ }
+ if isInterfaceUp(intf) {
+ addrs, err := nw.Addrs(intf)
+ if err != nil {
+ return nil, err
+ }
+ glog.V(4).Infof("Interface %q has %d addresses :%v.", intfName, len(addrs), addrs)
+ finalIP, err := getFinalIP(addrs)
+ if err != nil {
+ return nil, err
+ }
+ if finalIP != nil {
+ glog.V(4).Infof("valid IPv4 address for interface %q found as %v.", intfName, finalIP)
+ return finalIP, nil
+ }
+ }
+
+ return nil, nil
+}
+
+func flagsSet(flags net.Flags, test net.Flags) bool {
+ return flags&test != 0
+}
+
+func flagsClear(flags net.Flags, test net.Flags) bool {
+ return flags&test == 0
+}
+
+func chooseHostInterfaceNativeGo() (net.IP, error) {
+ intfs, err := net.Interfaces()
+ if err != nil {
+ return nil, err
+ }
+ i := 0
+ var ip net.IP
+ for i = range intfs {
+ if flagsSet(intfs[i].Flags, net.FlagUp) && flagsClear(intfs[i].Flags, net.FlagLoopback|net.FlagPointToPoint) {
+ addrs, err := intfs[i].Addrs()
+ if err != nil {
+ return nil, err
+ }
+ if len(addrs) > 0 {
+ for _, addr := range addrs {
+ if addrIP, _, err := net.ParseCIDR(addr.String()); err == nil {
+ if addrIP.To4() != nil {
+ ip = addrIP.To4()
+ if !ip.IsLinkLocalMulticast() && !ip.IsLinkLocalUnicast() {
+ break
+ }
+ }
+ }
+ }
+ if ip != nil {
+ // This interface should suffice.
+ break
+ }
+ }
+ }
+ }
+ if ip == nil {
+ return nil, fmt.Errorf("no acceptable interface from host")
+ }
+ glog.V(4).Infof("Choosing interface %s (IP %v) as default", intfs[i].Name, ip)
+ return ip, nil
+}
+
+//ChooseHostInterface is a method used fetch an IP for a daemon.
+//It uses data from /proc/net/route file.
+//For a node with no internet connection ,it returns error
+//For a multi n/w interface node it returns the IP of the interface with gateway on it.
+func ChooseHostInterface() (net.IP, error) {
+ inFile, err := os.Open("/proc/net/route")
+ if err != nil {
+ if os.IsNotExist(err) {
+ return chooseHostInterfaceNativeGo()
+ }
+ return nil, err
+ }
+ defer inFile.Close()
+ var nw networkInterfacer = networkInterface{}
+ return chooseHostInterfaceFromRoute(inFile, nw)
+}
+
+type networkInterfacer interface {
+ InterfaceByName(intfName string) (*net.Interface, error)
+ Addrs(intf *net.Interface) ([]net.Addr, error)
+}
+
+type networkInterface struct{}
+
+func (_ networkInterface) InterfaceByName(intfName string) (*net.Interface, error) {
+ intf, err := net.InterfaceByName(intfName)
+ if err != nil {
+ return nil, err
+ }
+ return intf, nil
+}
+
+func (_ networkInterface) Addrs(intf *net.Interface) ([]net.Addr, error) {
+ addrs, err := intf.Addrs()
+ if err != nil {
+ return nil, err
+ }
+ return addrs, nil
+}
+
+func chooseHostInterfaceFromRoute(inFile io.Reader, nw networkInterfacer) (net.IP, error) {
+ routes, err := getRoutes(inFile)
+ if err != nil {
+ return nil, err
+ }
+ zero := net.IP{0, 0, 0, 0}
+ var finalIP net.IP
+ for i := range routes {
+ //find interface with gateway
+ if routes[i].Destination.Equal(zero) {
+ glog.V(4).Infof("Default route transits interface %q", routes[i].Interface)
+ finalIP, err := getIPFromInterface(routes[i].Interface, nw)
+ if err != nil {
+ return nil, err
+ }
+ if finalIP != nil {
+ glog.V(4).Infof("Choosing IP %v ", finalIP)
+ return finalIP, nil
+ }
+ }
+ }
+ glog.V(4).Infof("No valid IP found")
+ if finalIP == nil {
+ return nil, fmt.Errorf("Unable to select an IP.")
+ }
+ return nil, nil
+}
+
+// If bind-address is usable, return it directly
+// If bind-address is not usable (unset, 0.0.0.0, or loopback), we will use the host's default
+// interface.
+func ChooseBindAddress(bindAddress net.IP) (net.IP, error) {
+ if bindAddress == nil || bindAddress.IsUnspecified() || bindAddress.IsLoopback() {
+ hostIP, err := ChooseHostInterface()
+ if err != nil {
+ return nil, err
+ }
+ bindAddress = hostIP
+ }
+ return bindAddress, nil
+}
diff --git a/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/net/port_range.go b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/net/port_range.go
new file mode 100644
index 0000000..6afdbf2
--- /dev/null
+++ b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/net/port_range.go
@@ -0,0 +1,108 @@
+/*
+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 net
+
+import (
+ "fmt"
+ "strconv"
+ "strings"
+)
+
+// PortRange represents a range of TCP/UDP ports. To represent a single port,
+// set Size to 1.
+type PortRange struct {
+ Base int
+ Size int
+}
+
+// Contains tests whether a given port falls within the PortRange.
+func (pr *PortRange) Contains(p int) bool {
+ return (p >= pr.Base) && ((p - pr.Base) < pr.Size)
+}
+
+// String converts the PortRange to a string representation, which can be
+// parsed by PortRange.Set or ParsePortRange.
+func (pr PortRange) String() string {
+ if pr.Size == 0 {
+ return ""
+ }
+ return fmt.Sprintf("%d-%d", pr.Base, pr.Base+pr.Size-1)
+}
+
+// Set parses a string of the form "min-max", inclusive at both ends, and
+// sets the PortRange from it. This is part of the flag.Value and pflag.Value
+// interfaces.
+func (pr *PortRange) Set(value string) error {
+ value = strings.TrimSpace(value)
+
+ // TODO: Accept "80" syntax
+ // TODO: Accept "80+8" syntax
+
+ if value == "" {
+ pr.Base = 0
+ pr.Size = 0
+ return nil
+ }
+
+ hyphenIndex := strings.Index(value, "-")
+ if hyphenIndex == -1 {
+ return fmt.Errorf("expected hyphen in port range")
+ }
+
+ var err error
+ var low int
+ var high int
+ low, err = strconv.Atoi(value[:hyphenIndex])
+ if err == nil {
+ high, err = strconv.Atoi(value[hyphenIndex+1:])
+ }
+ if err != nil {
+ return fmt.Errorf("unable to parse port range: %s", value)
+ }
+
+ if high < low {
+ return fmt.Errorf("end port cannot be less than start port: %s", value)
+ }
+ pr.Base = low
+ pr.Size = 1 + high - low
+ return nil
+}
+
+// Type returns a descriptive string about this type. This is part of the
+// pflag.Value interface.
+func (*PortRange) Type() string {
+ return "portRange"
+}
+
+// ParsePortRange parses a string of the form "min-max", inclusive at both
+// ends, and initializs a new PortRange from it.
+func ParsePortRange(value string) (*PortRange, error) {
+ pr := &PortRange{}
+ err := pr.Set(value)
+ if err != nil {
+ return nil, err
+ }
+ return pr, nil
+}
+
+func ParsePortRangeOrDie(value string) *PortRange {
+ pr, err := ParsePortRange(value)
+ if err != nil {
+ panic(fmt.Sprintf("couldn't parse port range %q: %v", value, err))
+ }
+ return pr
+}
diff --git a/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/net/port_split.go b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/net/port_split.go
new file mode 100644
index 0000000..29c985e
--- /dev/null
+++ b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/net/port_split.go
@@ -0,0 +1,77 @@
+/*
+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 net
+
+import (
+ "strings"
+
+ "k8s.io/kubernetes/pkg/util/sets"
+)
+
+var validSchemes = sets.NewString("http", "https", "")
+
+// SplitSchemeNamePort takes a string of the following forms:
+// * "<name>", returns "", "<name>","", true
+// * "<name>:<port>", returns "", "<name>","<port>",true
+// * "<scheme>:<name>:<port>", returns "<scheme>","<name>","<port>",true
+//
+// Name must be non-empty or valid will be returned false.
+// Scheme must be "http" or "https" if specified
+// Port is returned as a string, and it is not required to be numeric (could be
+// used for a named port, for example).
+func SplitSchemeNamePort(id string) (scheme, name, port string, valid bool) {
+ parts := strings.Split(id, ":")
+ switch len(parts) {
+ case 1:
+ name = parts[0]
+ case 2:
+ name = parts[0]
+ port = parts[1]
+ case 3:
+ scheme = parts[0]
+ name = parts[1]
+ port = parts[2]
+ default:
+ return "", "", "", false
+ }
+
+ if len(name) > 0 && validSchemes.Has(scheme) {
+ return scheme, name, port, true
+ } else {
+ return "", "", "", false
+ }
+}
+
+// JoinSchemeNamePort returns a string that specifies the scheme, name, and port:
+// * "<name>"
+// * "<name>:<port>"
+// * "<scheme>:<name>:<port>"
+// None of the parameters may contain a ':' character
+// Name is required
+// Scheme must be "", "http", or "https"
+func JoinSchemeNamePort(scheme, name, port string) string {
+ if len(scheme) > 0 {
+ // Must include three segments to specify scheme
+ return scheme + ":" + name + ":" + port
+ }
+ if len(port) > 0 {
+ // Must include two segments to specify port
+ return name + ":" + port
+ }
+ // Return name alone
+ return name
+}
diff --git a/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/net/sets/README.md b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/net/sets/README.md
new file mode 100644
index 0000000..b0f238a
--- /dev/null
+++ b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/net/sets/README.md
@@ -0,0 +1,17 @@
+This package contains hand-coded set implementations that should be similar to
+the autogenerated ones in `pkg/util/sets`.
+
+We can't simply use net.IPNet as a map-key in Go (because it contains a
+`[]byte`).
+
+We could use the same workaround we use here (a string representation as the
+key) to autogenerate sets. If we do that, or decide on an alternate approach,
+we should replace the implementations in this package with the autogenerated
+versions.
+
+It is expected that callers will alias this import as `netsets`
+i.e. `import netsets "k8s.io/kubernetes/pkg/util/net/sets"`
+
+
+
+[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/pkg/util/net/sets/README.md?pixel)]()
diff --git a/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/net/sets/ipnet.go b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/net/sets/ipnet.go
new file mode 100644
index 0000000..5b6fe93
--- /dev/null
+++ b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/net/sets/ipnet.go
@@ -0,0 +1,119 @@
+/*
+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 sets
+
+import (
+ "net"
+ "strings"
+)
+
+type IPNet map[string]*net.IPNet
+
+func ParseIPNets(specs ...string) (IPNet, error) {
+ ipnetset := make(IPNet)
+ for _, spec := range specs {
+ spec = strings.TrimSpace(spec)
+ _, ipnet, err := net.ParseCIDR(spec)
+ if err != nil {
+ return nil, err
+ }
+ k := ipnet.String() // In case of normalization
+ ipnetset[k] = ipnet
+ }
+ return ipnetset, nil
+}
+
+// Insert adds items to the set.
+func (s IPNet) Insert(items ...*net.IPNet) {
+ for _, item := range items {
+ s[item.String()] = item
+ }
+}
+
+// Delete removes all items from the set.
+func (s IPNet) Delete(items ...*net.IPNet) {
+ for _, item := range items {
+ delete(s, item.String())
+ }
+}
+
+// Has returns true if and only if item is contained in the set.
+func (s IPNet) Has(item *net.IPNet) bool {
+ _, contained := s[item.String()]
+ return contained
+}
+
+// HasAll returns true if and only if all items are contained in the set.
+func (s IPNet) HasAll(items ...*net.IPNet) bool {
+ for _, item := range items {
+ if !s.Has(item) {
+ return false
+ }
+ }
+ return true
+}
+
+// Difference returns a set of objects that are not in s2
+// For example:
+// s1 = {a1, a2, a3}
+// s2 = {a1, a2, a4, a5}
+// s1.Difference(s2) = {a3}
+// s2.Difference(s1) = {a4, a5}
+func (s IPNet) Difference(s2 IPNet) IPNet {
+ result := make(IPNet)
+ for k, i := range s {
+ _, found := s2[k]
+ if found {
+ continue
+ }
+ result[k] = i
+ }
+ return result
+}
+
+// StringSlice returns a []string with the String representation of each element in the set.
+// Order is undefined.
+func (s IPNet) StringSlice() []string {
+ a := make([]string, 0, len(s))
+ for k := range s {
+ a = append(a, k)
+ }
+ return a
+}
+
+// IsSuperset returns true if and only if s1 is a superset of s2.
+func (s1 IPNet) IsSuperset(s2 IPNet) bool {
+ for k := range s2 {
+ _, found := s1[k]
+ if !found {
+ return false
+ }
+ }
+ return true
+}
+
+// Equal returns true if and only if s1 is equal (as a set) to s2.
+// Two sets are equal if their membership is identical.
+// (In practice, this means same elements, order doesn't matter)
+func (s1 IPNet) Equal(s2 IPNet) bool {
+ return len(s1) == len(s2) && s1.IsSuperset(s2)
+}
+
+// Len returns the size of the set.
+func (s IPNet) Len() int {
+ return len(s)
+}
diff --git a/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/net/util.go b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/net/util.go
new file mode 100644
index 0000000..1348f4d
--- /dev/null
+++ b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/net/util.go
@@ -0,0 +1,36 @@
+/*
+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 net
+
+import (
+ "net"
+ "reflect"
+)
+
+// IPNetEqual checks if the two input IPNets are representing the same subnet.
+// For example,
+// 10.0.0.1/24 and 10.0.0.0/24 are the same subnet.
+// 10.0.0.1/24 and 10.0.0.0/25 are not the same subnet.
+func IPNetEqual(ipnet1, ipnet2 *net.IPNet) bool {
+ if ipnet1 == nil || ipnet2 == nil {
+ return false
+ }
+ if reflect.DeepEqual(ipnet1.Mask, ipnet2.Mask) && ipnet1.Contains(ipnet2.IP) && ipnet2.Contains(ipnet1.IP) {
+ return true
+ }
+ return false
+}
diff --git a/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/parsers/parsers.go b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/parsers/parsers.go
new file mode 100644
index 0000000..4e70cc6
--- /dev/null
+++ b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/parsers/parsers.go
@@ -0,0 +1,54 @@
+/*
+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 parsers
+
+import (
+ "fmt"
+
+ dockerref "github.com/docker/distribution/reference"
+)
+
+const (
+ DefaultImageTag = "latest"
+)
+
+// ParseImageName parses a docker image string into three parts: repo, tag and digest.
+// If both tag and digest are empty, a default image tag will be returned.
+func ParseImageName(image string) (string, string, string, error) {
+ named, err := dockerref.ParseNamed(image)
+ if err != nil {
+ return "", "", "", fmt.Errorf("couldn't parse image name: %v", err)
+ }
+
+ repoToPull := named.Name()
+ var tag, digest string
+
+ tagged, ok := named.(dockerref.Tagged)
+ if ok {
+ tag = tagged.Tag()
+ }
+
+ digested, ok := named.(dockerref.Digested)
+ if ok {
+ digest = digested.Digest().String()
+ }
+ // If no tag was specified, use the default "latest".
+ if len(tag) == 0 && len(digest) == 0 {
+ tag = DefaultImageTag
+ }
+ return repoToPull, tag, digest, nil
+}
diff --git a/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/rand/rand.go b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/rand/rand.go
new file mode 100644
index 0000000..134c152
--- /dev/null
+++ b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/rand/rand.go
@@ -0,0 +1,83 @@
+/*
+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 rand provides utilities related to randomization.
+package rand
+
+import (
+ "math/rand"
+ "sync"
+ "time"
+)
+
+var letters = []rune("abcdefghijklmnopqrstuvwxyz0123456789")
+var numLetters = len(letters)
+var rng = struct {
+ sync.Mutex
+ rand *rand.Rand
+}{
+ rand: rand.New(rand.NewSource(time.Now().UTC().UnixNano())),
+}
+
+// Intn generates an integer in range [0,max).
+// By design this should panic if input is invalid, <= 0.
+func Intn(max int) int {
+ rng.Lock()
+ defer rng.Unlock()
+ return rng.rand.Intn(max)
+}
+
+// IntnRange generates an integer in range [min,max).
+// By design this should panic if input is invalid, <= 0.
+func IntnRange(min, max int) int {
+ rng.Lock()
+ defer rng.Unlock()
+ return rng.rand.Intn(max-min) + min
+}
+
+// IntnRange generates an int64 integer in range [min,max).
+// By design this should panic if input is invalid, <= 0.
+func Int63nRange(min, max int64) int64 {
+ rng.Lock()
+ defer rng.Unlock()
+ return rng.rand.Int63n(max-min) + min
+}
+
+// Seed seeds the rng with the provided seed.
+func Seed(seed int64) {
+ rng.Lock()
+ defer rng.Unlock()
+
+ rng.rand = rand.New(rand.NewSource(seed))
+}
+
+// Perm returns, as a slice of n ints, a pseudo-random permutation of the integers [0,n)
+// from the default Source.
+func Perm(n int) []int {
+ rng.Lock()
+ defer rng.Unlock()
+ return rng.rand.Perm(n)
+}
+
+// String generates a random alphanumeric string n characters long. This will
+// panic if n is less than zero.
+func String(length int) string {
+ b := make([]rune, length)
+ for i := range b {
+ b[i] = letters[Intn(numLetters)]
+ }
+ return string(b)
+}
diff --git a/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/resource_container_linux.go b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/resource_container_linux.go
new file mode 100644
index 0000000..a844e4c
--- /dev/null
+++ b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/resource_container_linux.go
@@ -0,0 +1,49 @@
+// +build linux
+
+/*
+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 util
+
+import (
+ "os"
+ "syscall"
+
+ "github.com/opencontainers/runc/libcontainer/cgroups/fs"
+ "github.com/opencontainers/runc/libcontainer/configs"
+)
+
+// Creates resource-only containerName if it does not already exist and moves
+// the current process to it.
+//
+// containerName must be an absolute container name.
+func RunInResourceContainer(containerName string) error {
+ manager := fs.Manager{
+ Cgroups: &configs.Cgroup{
+ Parent: "/",
+ Name: containerName,
+ Resources: &configs.Resources{
+ AllowAllDevices: true,
+ },
+ },
+ }
+
+ return manager.Apply(os.Getpid())
+}
+
+func ApplyRLimitForSelf(maxOpenFiles uint64) {
+ syscall.Setrlimit(syscall.RLIMIT_NOFILE, &syscall.Rlimit{Max: maxOpenFiles, Cur: maxOpenFiles})
+}
diff --git a/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/resource_container_unsupported.go b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/resource_container_unsupported.go
new file mode 100644
index 0000000..ba861b0
--- /dev/null
+++ b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/resource_container_unsupported.go
@@ -0,0 +1,31 @@
+// +build !linux
+
+/*
+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 util
+
+import (
+ "errors"
+)
+
+func RunInResourceContainer(containerName string) error {
+ return errors.New("resource-only containers unsupported in this platform")
+}
+
+func ApplyRLimitForSelf(maxOpenFiles uint64) error {
+ return errors.New("SetRLimit unsupported in this platform")
+}
diff --git a/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/runner.go b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/runner.go
new file mode 100644
index 0000000..9e977ee
--- /dev/null
+++ b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/runner.go
@@ -0,0 +1,58 @@
+/*
+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 util
+
+import (
+ "sync"
+)
+
+// Runner is an abstraction to make it easy to start and stop groups of things that can be
+// described by a single function which waits on a channel close to exit.
+type Runner struct {
+ lock sync.Mutex
+ loopFuncs []func(stop chan struct{})
+ stop *chan struct{}
+}
+
+// NewRunner makes a runner for the given function(s). The function(s) should loop until
+// the channel is closed.
+func NewRunner(f ...func(stop chan struct{})) *Runner {
+ return &Runner{loopFuncs: f}
+}
+
+// Start begins running.
+func (r *Runner) Start() {
+ r.lock.Lock()
+ defer r.lock.Unlock()
+ if r.stop == nil {
+ c := make(chan struct{})
+ r.stop = &c
+ for i := range r.loopFuncs {
+ go r.loopFuncs[i](*r.stop)
+ }
+ }
+}
+
+// Stop stops running.
+func (r *Runner) Stop() {
+ r.lock.Lock()
+ defer r.lock.Unlock()
+ if r.stop != nil {
+ close(*r.stop)
+ r.stop = nil
+ }
+}
diff --git a/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/runtime/runtime.go b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/runtime/runtime.go
new file mode 100644
index 0000000..464d3ee
--- /dev/null
+++ b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/runtime/runtime.go
@@ -0,0 +1,94 @@
+/*
+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 runtime
+
+import (
+ "fmt"
+ "github.com/golang/glog"
+ "runtime"
+)
+
+// For testing, bypass HandleCrash.
+var ReallyCrash bool
+
+// PanicHandlers is a list of functions which will be invoked when a panic happens.
+var PanicHandlers = []func(interface{}){logPanic}
+
+//TODO search the public functions
+// HandleCrash simply catches a crash and logs an error. Meant to be called via defer.
+// Additional context-specific handlers can be provided, and will be called in case of panic
+func HandleCrash(additionalHandlers ...func(interface{})) {
+ if ReallyCrash {
+ return
+ }
+ if r := recover(); r != nil {
+ for _, fn := range PanicHandlers {
+ fn(r)
+ }
+ for _, fn := range additionalHandlers {
+ fn(r)
+ }
+ }
+}
+
+// logPanic logs the caller tree when a panic occurs.
+func logPanic(r interface{}) {
+ callers := ""
+ for i := 0; true; i++ {
+ _, file, line, ok := runtime.Caller(i)
+ if !ok {
+ break
+ }
+ callers = callers + fmt.Sprintf("%v:%v\n", file, line)
+ }
+ glog.Errorf("Recovered from panic: %#v (%v)\n%v", r, r, callers)
+}
+
+// ErrorHandlers is a list of functions which will be invoked when an unreturnable
+// error occurs.
+var ErrorHandlers = []func(error){logError}
+
+// HandlerError is a method to invoke when a non-user facing piece of code cannot
+// return an error and needs to indicate it has been ignored. Invoking this method
+// is preferable to logging the error - the default behavior is to log but the
+// errors may be sent to a remote server for analysis.
+func HandleError(err error) {
+ // this is sometimes called with a nil error. We probably shouldn't fail and should do nothing instead
+ if err == nil {
+ return
+ }
+
+ for _, fn := range ErrorHandlers {
+ fn(err)
+ }
+}
+
+// logError prints an error with the call stack of the location it was reported
+func logError(err error) {
+ glog.ErrorDepth(2, err)
+}
+
+// GetCaller returns the caller of the function that calls it.
+func GetCaller() string {
+ var pc [1]uintptr
+ runtime.Callers(3, pc[:])
+ f := runtime.FuncForPC(pc[0])
+ if f == nil {
+ return fmt.Sprintf("Unable to find caller")
+ }
+ return f.Name()
+}
diff --git a/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/sets/byte.go b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/sets/byte.go
new file mode 100644
index 0000000..45f5d4f
--- /dev/null
+++ b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/sets/byte.go
@@ -0,0 +1,194 @@
+/*
+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 set-gen. Do not edit it manually!
+
+package sets
+
+import (
+ "reflect"
+ "sort"
+)
+
+// sets.Byte is a set of bytes, implemented via map[byte]struct{} for minimal memory consumption.
+type Byte map[byte]Empty
+
+// New creates a Byte from a list of values.
+func NewByte(items ...byte) Byte {
+ ss := Byte{}
+ ss.Insert(items...)
+ return ss
+}
+
+// ByteKeySet creates a Byte from a keys of a map[byte](? extends interface{}).
+// If the value passed in is not actually a map, this will panic.
+func ByteKeySet(theMap interface{}) Byte {
+ v := reflect.ValueOf(theMap)
+ ret := Byte{}
+
+ for _, keyValue := range v.MapKeys() {
+ ret.Insert(keyValue.Interface().(byte))
+ }
+ return ret
+}
+
+// Insert adds items to the set.
+func (s Byte) Insert(items ...byte) {
+ for _, item := range items {
+ s[item] = Empty{}
+ }
+}
+
+// Delete removes all items from the set.
+func (s Byte) Delete(items ...byte) {
+ for _, item := range items {
+ delete(s, item)
+ }
+}
+
+// Has returns true if and only if item is contained in the set.
+func (s Byte) Has(item byte) bool {
+ _, contained := s[item]
+ return contained
+}
+
+// HasAll returns true if and only if all items are contained in the set.
+func (s Byte) HasAll(items ...byte) bool {
+ for _, item := range items {
+ if !s.Has(item) {
+ return false
+ }
+ }
+ return true
+}
+
+// HasAny returns true if any items are contained in the set.
+func (s Byte) HasAny(items ...byte) bool {
+ for _, item := range items {
+ if s.Has(item) {
+ return true
+ }
+ }
+ return false
+}
+
+// Difference returns a set of objects that are not in s2
+// For example:
+// s1 = {a1, a2, a3}
+// s2 = {a1, a2, a4, a5}
+// s1.Difference(s2) = {a3}
+// s2.Difference(s1) = {a4, a5}
+func (s Byte) Difference(s2 Byte) Byte {
+ result := NewByte()
+ for key := range s {
+ if !s2.Has(key) {
+ result.Insert(key)
+ }
+ }
+ return result
+}
+
+// Union returns a new set which includes items in either s1 or s2.
+// For example:
+// s1 = {a1, a2}
+// s2 = {a3, a4}
+// s1.Union(s2) = {a1, a2, a3, a4}
+// s2.Union(s1) = {a1, a2, a3, a4}
+func (s1 Byte) Union(s2 Byte) Byte {
+ result := NewByte()
+ for key := range s1 {
+ result.Insert(key)
+ }
+ for key := range s2 {
+ result.Insert(key)
+ }
+ return result
+}
+
+// Intersection returns a new set which includes the item in BOTH s1 and s2
+// For example:
+// s1 = {a1, a2}
+// s2 = {a2, a3}
+// s1.Intersection(s2) = {a2}
+func (s1 Byte) Intersection(s2 Byte) Byte {
+ var walk, other Byte
+ result := NewByte()
+ if s1.Len() < s2.Len() {
+ walk = s1
+ other = s2
+ } else {
+ walk = s2
+ other = s1
+ }
+ for key := range walk {
+ if other.Has(key) {
+ result.Insert(key)
+ }
+ }
+ return result
+}
+
+// IsSuperset returns true if and only if s1 is a superset of s2.
+func (s1 Byte) IsSuperset(s2 Byte) bool {
+ for item := range s2 {
+ if !s1.Has(item) {
+ return false
+ }
+ }
+ return true
+}
+
+// Equal returns true if and only if s1 is equal (as a set) to s2.
+// Two sets are equal if their membership is identical.
+// (In practice, this means same elements, order doesn't matter)
+func (s1 Byte) Equal(s2 Byte) bool {
+ return len(s1) == len(s2) && s1.IsSuperset(s2)
+}
+
+type sortableSliceOfByte []byte
+
+func (s sortableSliceOfByte) Len() int { return len(s) }
+func (s sortableSliceOfByte) Less(i, j int) bool { return lessByte(s[i], s[j]) }
+func (s sortableSliceOfByte) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
+
+// List returns the contents as a sorted byte slice.
+func (s Byte) List() []byte {
+ res := make(sortableSliceOfByte, 0, len(s))
+ for key := range s {
+ res = append(res, key)
+ }
+ sort.Sort(res)
+ return []byte(res)
+}
+
+// Returns a single element from the set.
+func (s Byte) PopAny() (byte, bool) {
+ for key := range s {
+ s.Delete(key)
+ return key, true
+ }
+ var zeroValue byte
+ return zeroValue, false
+}
+
+// Len returns the size of the set.
+func (s Byte) Len() int {
+ return len(s)
+}
+
+func lessByte(lhs, rhs byte) bool {
+ return lhs < rhs
+}
diff --git a/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/sets/doc.go b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/sets/doc.go
new file mode 100644
index 0000000..c5e5416
--- /dev/null
+++ b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/sets/doc.go
@@ -0,0 +1,20 @@
+/*
+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 set-gen. Do not edit it manually!
+
+// Package sets has auto-generated set types.
+package sets
diff --git a/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/sets/empty.go b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/sets/empty.go
new file mode 100644
index 0000000..5654edd
--- /dev/null
+++ b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/sets/empty.go
@@ -0,0 +1,23 @@
+/*
+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 set-gen. Do not edit it manually!
+
+package sets
+
+// Empty is public since it is used by some internal API objects for conversions between external
+// string arrays and internal sets, and conversion logic requires public types today.
+type Empty struct{}
diff --git a/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/sets/int.go b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/sets/int.go
new file mode 100644
index 0000000..4b8c331
--- /dev/null
+++ b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/sets/int.go
@@ -0,0 +1,194 @@
+/*
+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 set-gen. Do not edit it manually!
+
+package sets
+
+import (
+ "reflect"
+ "sort"
+)
+
+// sets.Int is a set of ints, implemented via map[int]struct{} for minimal memory consumption.
+type Int map[int]Empty
+
+// New creates a Int from a list of values.
+func NewInt(items ...int) Int {
+ ss := Int{}
+ ss.Insert(items...)
+ return ss
+}
+
+// IntKeySet creates a Int from a keys of a map[int](? extends interface{}).
+// If the value passed in is not actually a map, this will panic.
+func IntKeySet(theMap interface{}) Int {
+ v := reflect.ValueOf(theMap)
+ ret := Int{}
+
+ for _, keyValue := range v.MapKeys() {
+ ret.Insert(keyValue.Interface().(int))
+ }
+ return ret
+}
+
+// Insert adds items to the set.
+func (s Int) Insert(items ...int) {
+ for _, item := range items {
+ s[item] = Empty{}
+ }
+}
+
+// Delete removes all items from the set.
+func (s Int) Delete(items ...int) {
+ for _, item := range items {
+ delete(s, item)
+ }
+}
+
+// Has returns true if and only if item is contained in the set.
+func (s Int) Has(item int) bool {
+ _, contained := s[item]
+ return contained
+}
+
+// HasAll returns true if and only if all items are contained in the set.
+func (s Int) HasAll(items ...int) bool {
+ for _, item := range items {
+ if !s.Has(item) {
+ return false
+ }
+ }
+ return true
+}
+
+// HasAny returns true if any items are contained in the set.
+func (s Int) HasAny(items ...int) bool {
+ for _, item := range items {
+ if s.Has(item) {
+ return true
+ }
+ }
+ return false
+}
+
+// Difference returns a set of objects that are not in s2
+// For example:
+// s1 = {a1, a2, a3}
+// s2 = {a1, a2, a4, a5}
+// s1.Difference(s2) = {a3}
+// s2.Difference(s1) = {a4, a5}
+func (s Int) Difference(s2 Int) Int {
+ result := NewInt()
+ for key := range s {
+ if !s2.Has(key) {
+ result.Insert(key)
+ }
+ }
+ return result
+}
+
+// Union returns a new set which includes items in either s1 or s2.
+// For example:
+// s1 = {a1, a2}
+// s2 = {a3, a4}
+// s1.Union(s2) = {a1, a2, a3, a4}
+// s2.Union(s1) = {a1, a2, a3, a4}
+func (s1 Int) Union(s2 Int) Int {
+ result := NewInt()
+ for key := range s1 {
+ result.Insert(key)
+ }
+ for key := range s2 {
+ result.Insert(key)
+ }
+ return result
+}
+
+// Intersection returns a new set which includes the item in BOTH s1 and s2
+// For example:
+// s1 = {a1, a2}
+// s2 = {a2, a3}
+// s1.Intersection(s2) = {a2}
+func (s1 Int) Intersection(s2 Int) Int {
+ var walk, other Int
+ result := NewInt()
+ if s1.Len() < s2.Len() {
+ walk = s1
+ other = s2
+ } else {
+ walk = s2
+ other = s1
+ }
+ for key := range walk {
+ if other.Has(key) {
+ result.Insert(key)
+ }
+ }
+ return result
+}
+
+// IsSuperset returns true if and only if s1 is a superset of s2.
+func (s1 Int) IsSuperset(s2 Int) bool {
+ for item := range s2 {
+ if !s1.Has(item) {
+ return false
+ }
+ }
+ return true
+}
+
+// Equal returns true if and only if s1 is equal (as a set) to s2.
+// Two sets are equal if their membership is identical.
+// (In practice, this means same elements, order doesn't matter)
+func (s1 Int) Equal(s2 Int) bool {
+ return len(s1) == len(s2) && s1.IsSuperset(s2)
+}
+
+type sortableSliceOfInt []int
+
+func (s sortableSliceOfInt) Len() int { return len(s) }
+func (s sortableSliceOfInt) Less(i, j int) bool { return lessInt(s[i], s[j]) }
+func (s sortableSliceOfInt) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
+
+// List returns the contents as a sorted int slice.
+func (s Int) List() []int {
+ res := make(sortableSliceOfInt, 0, len(s))
+ for key := range s {
+ res = append(res, key)
+ }
+ sort.Sort(res)
+ return []int(res)
+}
+
+// Returns a single element from the set.
+func (s Int) PopAny() (int, bool) {
+ for key := range s {
+ s.Delete(key)
+ return key, true
+ }
+ var zeroValue int
+ return zeroValue, false
+}
+
+// Len returns the size of the set.
+func (s Int) Len() int {
+ return len(s)
+}
+
+func lessInt(lhs, rhs int) bool {
+ return lhs < rhs
+}
diff --git a/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/sets/int64.go b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/sets/int64.go
new file mode 100644
index 0000000..b6a97e7
--- /dev/null
+++ b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/sets/int64.go
@@ -0,0 +1,194 @@
+/*
+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 set-gen. Do not edit it manually!
+
+package sets
+
+import (
+ "reflect"
+ "sort"
+)
+
+// sets.Int64 is a set of int64s, implemented via map[int64]struct{} for minimal memory consumption.
+type Int64 map[int64]Empty
+
+// New creates a Int64 from a list of values.
+func NewInt64(items ...int64) Int64 {
+ ss := Int64{}
+ ss.Insert(items...)
+ return ss
+}
+
+// Int64KeySet creates a Int64 from a keys of a map[int64](? extends interface{}).
+// If the value passed in is not actually a map, this will panic.
+func Int64KeySet(theMap interface{}) Int64 {
+ v := reflect.ValueOf(theMap)
+ ret := Int64{}
+
+ for _, keyValue := range v.MapKeys() {
+ ret.Insert(keyValue.Interface().(int64))
+ }
+ return ret
+}
+
+// Insert adds items to the set.
+func (s Int64) Insert(items ...int64) {
+ for _, item := range items {
+ s[item] = Empty{}
+ }
+}
+
+// Delete removes all items from the set.
+func (s Int64) Delete(items ...int64) {
+ for _, item := range items {
+ delete(s, item)
+ }
+}
+
+// Has returns true if and only if item is contained in the set.
+func (s Int64) Has(item int64) bool {
+ _, contained := s[item]
+ return contained
+}
+
+// HasAll returns true if and only if all items are contained in the set.
+func (s Int64) HasAll(items ...int64) bool {
+ for _, item := range items {
+ if !s.Has(item) {
+ return false
+ }
+ }
+ return true
+}
+
+// HasAny returns true if any items are contained in the set.
+func (s Int64) HasAny(items ...int64) bool {
+ for _, item := range items {
+ if s.Has(item) {
+ return true
+ }
+ }
+ return false
+}
+
+// Difference returns a set of objects that are not in s2
+// For example:
+// s1 = {a1, a2, a3}
+// s2 = {a1, a2, a4, a5}
+// s1.Difference(s2) = {a3}
+// s2.Difference(s1) = {a4, a5}
+func (s Int64) Difference(s2 Int64) Int64 {
+ result := NewInt64()
+ for key := range s {
+ if !s2.Has(key) {
+ result.Insert(key)
+ }
+ }
+ return result
+}
+
+// Union returns a new set which includes items in either s1 or s2.
+// For example:
+// s1 = {a1, a2}
+// s2 = {a3, a4}
+// s1.Union(s2) = {a1, a2, a3, a4}
+// s2.Union(s1) = {a1, a2, a3, a4}
+func (s1 Int64) Union(s2 Int64) Int64 {
+ result := NewInt64()
+ for key := range s1 {
+ result.Insert(key)
+ }
+ for key := range s2 {
+ result.Insert(key)
+ }
+ return result
+}
+
+// Intersection returns a new set which includes the item in BOTH s1 and s2
+// For example:
+// s1 = {a1, a2}
+// s2 = {a2, a3}
+// s1.Intersection(s2) = {a2}
+func (s1 Int64) Intersection(s2 Int64) Int64 {
+ var walk, other Int64
+ result := NewInt64()
+ if s1.Len() < s2.Len() {
+ walk = s1
+ other = s2
+ } else {
+ walk = s2
+ other = s1
+ }
+ for key := range walk {
+ if other.Has(key) {
+ result.Insert(key)
+ }
+ }
+ return result
+}
+
+// IsSuperset returns true if and only if s1 is a superset of s2.
+func (s1 Int64) IsSuperset(s2 Int64) bool {
+ for item := range s2 {
+ if !s1.Has(item) {
+ return false
+ }
+ }
+ return true
+}
+
+// Equal returns true if and only if s1 is equal (as a set) to s2.
+// Two sets are equal if their membership is identical.
+// (In practice, this means same elements, order doesn't matter)
+func (s1 Int64) Equal(s2 Int64) bool {
+ return len(s1) == len(s2) && s1.IsSuperset(s2)
+}
+
+type sortableSliceOfInt64 []int64
+
+func (s sortableSliceOfInt64) Len() int { return len(s) }
+func (s sortableSliceOfInt64) Less(i, j int) bool { return lessInt64(s[i], s[j]) }
+func (s sortableSliceOfInt64) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
+
+// List returns the contents as a sorted int64 slice.
+func (s Int64) List() []int64 {
+ res := make(sortableSliceOfInt64, 0, len(s))
+ for key := range s {
+ res = append(res, key)
+ }
+ sort.Sort(res)
+ return []int64(res)
+}
+
+// Returns a single element from the set.
+func (s Int64) PopAny() (int64, bool) {
+ for key := range s {
+ s.Delete(key)
+ return key, true
+ }
+ var zeroValue int64
+ return zeroValue, false
+}
+
+// Len returns the size of the set.
+func (s Int64) Len() int {
+ return len(s)
+}
+
+func lessInt64(lhs, rhs int64) bool {
+ return lhs < rhs
+}
diff --git a/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/sets/string.go b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/sets/string.go
new file mode 100644
index 0000000..2094b32
--- /dev/null
+++ b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/sets/string.go
@@ -0,0 +1,194 @@
+/*
+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 set-gen. Do not edit it manually!
+
+package sets
+
+import (
+ "reflect"
+ "sort"
+)
+
+// sets.String is a set of strings, implemented via map[string]struct{} for minimal memory consumption.
+type String map[string]Empty
+
+// New creates a String from a list of values.
+func NewString(items ...string) String {
+ ss := String{}
+ ss.Insert(items...)
+ return ss
+}
+
+// StringKeySet creates a String from a keys of a map[string](? extends interface{}).
+// If the value passed in is not actually a map, this will panic.
+func StringKeySet(theMap interface{}) String {
+ v := reflect.ValueOf(theMap)
+ ret := String{}
+
+ for _, keyValue := range v.MapKeys() {
+ ret.Insert(keyValue.Interface().(string))
+ }
+ return ret
+}
+
+// Insert adds items to the set.
+func (s String) Insert(items ...string) {
+ for _, item := range items {
+ s[item] = Empty{}
+ }
+}
+
+// Delete removes all items from the set.
+func (s String) Delete(items ...string) {
+ for _, item := range items {
+ delete(s, item)
+ }
+}
+
+// Has returns true if and only if item is contained in the set.
+func (s String) Has(item string) bool {
+ _, contained := s[item]
+ return contained
+}
+
+// HasAll returns true if and only if all items are contained in the set.
+func (s String) HasAll(items ...string) bool {
+ for _, item := range items {
+ if !s.Has(item) {
+ return false
+ }
+ }
+ return true
+}
+
+// HasAny returns true if any items are contained in the set.
+func (s String) HasAny(items ...string) bool {
+ for _, item := range items {
+ if s.Has(item) {
+ return true
+ }
+ }
+ return false
+}
+
+// Difference returns a set of objects that are not in s2
+// For example:
+// s1 = {a1, a2, a3}
+// s2 = {a1, a2, a4, a5}
+// s1.Difference(s2) = {a3}
+// s2.Difference(s1) = {a4, a5}
+func (s String) Difference(s2 String) String {
+ result := NewString()
+ for key := range s {
+ if !s2.Has(key) {
+ result.Insert(key)
+ }
+ }
+ return result
+}
+
+// Union returns a new set which includes items in either s1 or s2.
+// For example:
+// s1 = {a1, a2}
+// s2 = {a3, a4}
+// s1.Union(s2) = {a1, a2, a3, a4}
+// s2.Union(s1) = {a1, a2, a3, a4}
+func (s1 String) Union(s2 String) String {
+ result := NewString()
+ for key := range s1 {
+ result.Insert(key)
+ }
+ for key := range s2 {
+ result.Insert(key)
+ }
+ return result
+}
+
+// Intersection returns a new set which includes the item in BOTH s1 and s2
+// For example:
+// s1 = {a1, a2}
+// s2 = {a2, a3}
+// s1.Intersection(s2) = {a2}
+func (s1 String) Intersection(s2 String) String {
+ var walk, other String
+ result := NewString()
+ if s1.Len() < s2.Len() {
+ walk = s1
+ other = s2
+ } else {
+ walk = s2
+ other = s1
+ }
+ for key := range walk {
+ if other.Has(key) {
+ result.Insert(key)
+ }
+ }
+ return result
+}
+
+// IsSuperset returns true if and only if s1 is a superset of s2.
+func (s1 String) IsSuperset(s2 String) bool {
+ for item := range s2 {
+ if !s1.Has(item) {
+ return false
+ }
+ }
+ return true
+}
+
+// Equal returns true if and only if s1 is equal (as a set) to s2.
+// Two sets are equal if their membership is identical.
+// (In practice, this means same elements, order doesn't matter)
+func (s1 String) Equal(s2 String) bool {
+ return len(s1) == len(s2) && s1.IsSuperset(s2)
+}
+
+type sortableSliceOfString []string
+
+func (s sortableSliceOfString) Len() int { return len(s) }
+func (s sortableSliceOfString) Less(i, j int) bool { return lessString(s[i], s[j]) }
+func (s sortableSliceOfString) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
+
+// List returns the contents as a sorted string slice.
+func (s String) List() []string {
+ res := make(sortableSliceOfString, 0, len(s))
+ for key := range s {
+ res = append(res, key)
+ }
+ sort.Sort(res)
+ return []string(res)
+}
+
+// Returns a single element from the set.
+func (s String) PopAny() (string, bool) {
+ for key := range s {
+ s.Delete(key)
+ return key, true
+ }
+ var zeroValue string
+ return zeroValue, false
+}
+
+// Len returns the size of the set.
+func (s String) Len() int {
+ return len(s)
+}
+
+func lessString(lhs, rhs string) bool {
+ return lhs < rhs
+}
diff --git a/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/string_flag.go b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/string_flag.go
new file mode 100644
index 0000000..9d6a00a
--- /dev/null
+++ b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/string_flag.go
@@ -0,0 +1,56 @@
+/*
+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 util
+
+// StringFlag is a string flag compatible with flags and pflags that keeps track of whether it had a value supplied or not.
+type StringFlag struct {
+ // If Set has been invoked this value is true
+ provided bool
+ // The exact value provided on the flag
+ value string
+}
+
+func NewStringFlag(defaultVal string) StringFlag {
+ return StringFlag{value: defaultVal}
+}
+
+func (f *StringFlag) Default(value string) {
+ f.value = value
+}
+
+func (f StringFlag) String() string {
+ return f.value
+}
+
+func (f StringFlag) Value() string {
+ return f.value
+}
+
+func (f *StringFlag) Set(value string) error {
+ f.value = value
+ f.provided = true
+
+ return nil
+}
+
+func (f StringFlag) Provided() bool {
+ return f.provided
+}
+
+func (f *StringFlag) Type() string {
+ return "string"
+}
diff --git a/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/template.go b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/template.go
new file mode 100644
index 0000000..d09d7dc
--- /dev/null
+++ b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/template.go
@@ -0,0 +1,48 @@
+/*
+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 util
+
+import (
+ "bytes"
+ "go/doc"
+ "io"
+ "strings"
+ "text/template"
+)
+
+func wrap(indent string, s string) string {
+ var buf bytes.Buffer
+ doc.ToText(&buf, s, indent, indent+" ", 80-len(indent))
+ return buf.String()
+}
+
+// ExecuteTemplate executes templateText with data and output written to w.
+func ExecuteTemplate(w io.Writer, templateText string, data interface{}) error {
+ t := template.New("top")
+ t.Funcs(template.FuncMap{
+ "trim": strings.TrimSpace,
+ "wrap": wrap,
+ })
+ template.Must(t.Parse(templateText))
+ return t.Execute(w, data)
+}
+
+func ExecuteTemplateToString(templateText string, data interface{}) (string, error) {
+ b := bytes.Buffer{}
+ err := ExecuteTemplate(&b, templateText, data)
+ return b.String(), err
+}
diff --git a/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/trace.go b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/trace.go
new file mode 100644
index 0000000..fe93db8
--- /dev/null
+++ b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/trace.go
@@ -0,0 +1,72 @@
+/*
+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 util
+
+import (
+ "bytes"
+ "fmt"
+ "time"
+
+ "github.com/golang/glog"
+)
+
+type traceStep struct {
+ stepTime time.Time
+ msg string
+}
+
+type Trace struct {
+ name string
+ startTime time.Time
+ steps []traceStep
+}
+
+func NewTrace(name string) *Trace {
+ return &Trace{name, time.Now(), nil}
+}
+
+func (t *Trace) Step(msg string) {
+ if t.steps == nil {
+ // traces almost always have less than 6 steps, do this to avoid more than a single allocation
+ t.steps = make([]traceStep, 0, 6)
+ }
+ t.steps = append(t.steps, traceStep{time.Now(), msg})
+}
+
+func (t *Trace) Log() {
+ endTime := time.Now()
+ var buffer bytes.Buffer
+
+ buffer.WriteString(fmt.Sprintf("Trace %q (started %v):\n", t.name, t.startTime))
+ lastStepTime := t.startTime
+ for _, step := range t.steps {
+ buffer.WriteString(fmt.Sprintf("[%v] [%v] %v\n", step.stepTime.Sub(t.startTime), step.stepTime.Sub(lastStepTime), step.msg))
+ lastStepTime = step.stepTime
+ }
+ buffer.WriteString(fmt.Sprintf("[%v] [%v] END\n", endTime.Sub(t.startTime), endTime.Sub(lastStepTime)))
+ glog.Info(buffer.String())
+}
+
+func (t *Trace) LogIfLong(threshold time.Duration) {
+ if time.Since(t.startTime) >= threshold {
+ t.Log()
+ }
+}
+
+func (t *Trace) TotalTime() time.Duration {
+ return time.Since(t.startTime)
+}
diff --git a/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/umask.go b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/umask.go
new file mode 100644
index 0000000..35ccce5
--- /dev/null
+++ b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/umask.go
@@ -0,0 +1,27 @@
+// +build !windows
+
+/*
+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 util
+
+import (
+ "syscall"
+)
+
+func Umask(mask int) (old int, err error) {
+ return syscall.Umask(mask), nil
+}
diff --git a/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/umask_windows.go b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/umask_windows.go
new file mode 100644
index 0000000..8c1b2cb
--- /dev/null
+++ b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/umask_windows.go
@@ -0,0 +1,27 @@
+// +build windows
+
+/*
+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 util
+
+import (
+ "errors"
+)
+
+func Umask(mask int) (old int, err error) {
+ return 0, errors.New("platform and architecture is not supported")
+}
diff --git a/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/util.go b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/util.go
new file mode 100644
index 0000000..7a94149
--- /dev/null
+++ b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/util.go
@@ -0,0 +1,147 @@
+/*
+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 util
+
+import (
+ "fmt"
+ "os"
+ "reflect"
+ "regexp"
+)
+
+// Takes a list of strings and compiles them into a list of regular expressions
+func CompileRegexps(regexpStrings []string) ([]*regexp.Regexp, error) {
+ regexps := []*regexp.Regexp{}
+ for _, regexpStr := range regexpStrings {
+ r, err := regexp.Compile(regexpStr)
+ if err != nil {
+ return []*regexp.Regexp{}, err
+ }
+ regexps = append(regexps, r)
+ }
+ return regexps, nil
+}
+
+// Detects if using systemd as the init system
+// Please note that simply reading /proc/1/cmdline can be misleading because
+// some installation of various init programs can automatically make /sbin/init
+// a symlink or even a renamed version of their main program.
+// TODO(dchen1107): realiably detects the init system using on the system:
+// systemd, upstart, initd, etc.
+func UsingSystemdInitSystem() bool {
+ if _, err := os.Stat("/run/systemd/system"); err == nil {
+ return true
+ }
+
+ return false
+}
+
+// Tests whether all pointer fields in a struct are nil. This is useful when,
+// for example, an API struct is handled by plugins which need to distinguish
+// "no plugin accepted this spec" from "this spec is empty".
+//
+// This function is only valid for structs and pointers to structs. Any other
+// type will cause a panic. Passing a typed nil pointer will return true.
+func AllPtrFieldsNil(obj interface{}) bool {
+ v := reflect.ValueOf(obj)
+ if !v.IsValid() {
+ panic(fmt.Sprintf("reflect.ValueOf() produced a non-valid Value for %#v", obj))
+ }
+ if v.Kind() == reflect.Ptr {
+ if v.IsNil() {
+ return true
+ }
+ v = v.Elem()
+ }
+ for i := 0; i < v.NumField(); i++ {
+ if v.Field(i).Kind() == reflect.Ptr && !v.Field(i).IsNil() {
+ return false
+ }
+ }
+ return true
+}
+
+func FileExists(filename string) (bool, error) {
+ if _, err := os.Stat(filename); os.IsNotExist(err) {
+ return false, nil
+ } else if err != nil {
+ return false, err
+ }
+ return true, nil
+}
+
+// borrowed from ioutil.ReadDir
+// ReadDir reads the directory named by dirname and returns
+// a list of directory entries, minus those with lstat errors
+func ReadDirNoExit(dirname string) ([]os.FileInfo, []error, error) {
+ if dirname == "" {
+ dirname = "."
+ }
+
+ f, err := os.Open(dirname)
+ if err != nil {
+ return nil, nil, err
+ }
+ defer f.Close()
+
+ names, err := f.Readdirnames(-1)
+ list := make([]os.FileInfo, 0, len(names))
+ errs := make([]error, 0, len(names))
+ for _, filename := range names {
+ fip, lerr := os.Lstat(dirname + "/" + filename)
+ if os.IsNotExist(lerr) {
+ // File disappeared between readdir + stat.
+ // Just treat it as if it didn't exist.
+ continue
+ }
+
+ list = append(list, fip)
+ errs = append(errs, lerr)
+ }
+
+ return list, errs, nil
+}
+
+// IntPtr returns a pointer to an int
+func IntPtr(i int) *int {
+ o := i
+ return &o
+}
+
+// Int32Ptr returns a pointer to an int32
+func Int32Ptr(i int32) *int32 {
+ o := i
+ return &o
+}
+
+// IntPtrDerefOr dereference the int ptr and returns it i not nil,
+// else returns def.
+func IntPtrDerefOr(ptr *int, def int) int {
+ if ptr != nil {
+ return *ptr
+ }
+ return def
+}
+
+// Int32PtrDerefOr dereference the int32 ptr and returns it i not nil,
+// else returns def.
+func Int32PtrDerefOr(ptr *int32, def int32) int32 {
+ if ptr != nil {
+ return *ptr
+ }
+ return def
+}
diff --git a/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/uuid.go b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/uuid.go
new file mode 100644
index 0000000..23abe11
--- /dev/null
+++ b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/uuid.go
@@ -0,0 +1,42 @@
+/*
+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 util
+
+import (
+ "sync"
+
+ "github.com/pborman/uuid"
+ "k8s.io/kubernetes/pkg/types"
+)
+
+var uuidLock sync.Mutex
+var lastUUID uuid.UUID
+
+func NewUUID() types.UID {
+ uuidLock.Lock()
+ defer uuidLock.Unlock()
+ result := uuid.NewUUID()
+ // The UUID package is naive and can generate identical UUIDs if the
+ // time interval is quick enough.
+ // The UUID uses 100 ns increments so it's short enough to actively
+ // wait for a new value.
+ for uuid.Equal(lastUUID, result) == true {
+ result = uuid.NewUUID()
+ }
+ lastUUID = result
+ return types.UID(result.String())
+}
diff --git a/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/validation/field/errors.go b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/validation/field/errors.go
new file mode 100644
index 0000000..b4a6c5c
--- /dev/null
+++ b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/validation/field/errors.go
@@ -0,0 +1,228 @@
+/*
+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 field
+
+import (
+ "encoding/json"
+ "fmt"
+ "strings"
+
+ utilerrors "k8s.io/kubernetes/pkg/util/errors"
+)
+
+// Error is an implementation of the 'error' interface, which represents a
+// field-level validation error.
+type Error struct {
+ Type ErrorType
+ Field string
+ BadValue interface{}
+ Detail string
+}
+
+var _ error = &Error{}
+
+// Error implements the error interface.
+func (v *Error) Error() string {
+ return fmt.Sprintf("%s: %s", v.Field, v.ErrorBody())
+}
+
+// ErrorBody returns the error message without the field name. This is useful
+// for building nice-looking higher-level error reporting.
+func (v *Error) ErrorBody() string {
+ var s string
+ switch v.Type {
+ case ErrorTypeRequired, ErrorTypeForbidden, ErrorTypeTooLong, ErrorTypeInternal:
+ s = fmt.Sprintf("%s", v.Type)
+ default:
+ var bad string
+ badBytes, err := json.Marshal(v.BadValue)
+ if err != nil {
+ bad = err.Error()
+ } else {
+ bad = string(badBytes)
+ }
+ s = fmt.Sprintf("%s: %s", v.Type, bad)
+ }
+ if len(v.Detail) != 0 {
+ s += fmt.Sprintf(": %s", v.Detail)
+ }
+ return s
+}
+
+// ErrorType is a machine readable value providing more detail about why
+// a field is invalid. These values are expected to match 1-1 with
+// CauseType in api/types.go.
+type ErrorType string
+
+// TODO: These values are duplicated in api/types.go, but there's a circular dep. Fix it.
+const (
+ // ErrorTypeNotFound is used to report failure to find a requested value
+ // (e.g. looking up an ID). See NotFound().
+ ErrorTypeNotFound ErrorType = "FieldValueNotFound"
+ // ErrorTypeRequired is used to report required values that are not
+ // provided (e.g. empty strings, null values, or empty arrays). See
+ // Required().
+ ErrorTypeRequired ErrorType = "FieldValueRequired"
+ // ErrorTypeDuplicate is used to report collisions of values that must be
+ // unique (e.g. unique IDs). See Duplicate().
+ ErrorTypeDuplicate ErrorType = "FieldValueDuplicate"
+ // ErrorTypeInvalid is used to report malformed values (e.g. failed regex
+ // match, too long, out of bounds). See Invalid().
+ ErrorTypeInvalid ErrorType = "FieldValueInvalid"
+ // ErrorTypeNotSupported is used to report unknown values for enumerated
+ // fields (e.g. a list of valid values). See NotSupported().
+ ErrorTypeNotSupported ErrorType = "FieldValueNotSupported"
+ // ErrorTypeForbidden is used to report valid (as per formatting rules)
+ // values which would be accepted under some conditions, but which are not
+ // permitted by the current conditions (such as security policy). See
+ // Forbidden().
+ ErrorTypeForbidden ErrorType = "FieldValueForbidden"
+ // ErrorTypeTooLong is used to report that the given value is too long.
+ // This is similar to ErrorTypeInvalid, but the error will not include the
+ // too-long value. See TooLong().
+ ErrorTypeTooLong ErrorType = "FieldValueTooLong"
+ // ErrorTypeInternal is used to report other errors that are not related
+ // to user input. See InternalError().
+ ErrorTypeInternal ErrorType = "InternalError"
+)
+
+// String converts a ErrorType into its corresponding canonical error message.
+func (t ErrorType) String() string {
+ switch t {
+ case ErrorTypeNotFound:
+ return "Not found"
+ case ErrorTypeRequired:
+ return "Required value"
+ case ErrorTypeDuplicate:
+ return "Duplicate value"
+ case ErrorTypeInvalid:
+ return "Invalid value"
+ case ErrorTypeNotSupported:
+ return "Unsupported value"
+ case ErrorTypeForbidden:
+ return "Forbidden"
+ case ErrorTypeTooLong:
+ return "Too long"
+ case ErrorTypeInternal:
+ return "Internal error"
+ default:
+ panic(fmt.Sprintf("unrecognized validation error: %q", string(t)))
+ }
+}
+
+// NotFound returns a *Error indicating "value not found". This is
+// used to report failure to find a requested value (e.g. looking up an ID).
+func NotFound(field *Path, value interface{}) *Error {
+ return &Error{ErrorTypeNotFound, field.String(), value, ""}
+}
+
+// Required returns a *Error indicating "value required". This is used
+// to report required values that are not provided (e.g. empty strings, null
+// values, or empty arrays).
+func Required(field *Path, detail string) *Error {
+ return &Error{ErrorTypeRequired, field.String(), "", detail}
+}
+
+// Duplicate returns a *Error indicating "duplicate value". This is
+// used to report collisions of values that must be unique (e.g. names or IDs).
+func Duplicate(field *Path, value interface{}) *Error {
+ return &Error{ErrorTypeDuplicate, field.String(), value, ""}
+}
+
+// Invalid returns a *Error indicating "invalid value". This is used
+// to report malformed values (e.g. failed regex match, too long, out of bounds).
+func Invalid(field *Path, value interface{}, detail string) *Error {
+ return &Error{ErrorTypeInvalid, field.String(), value, detail}
+}
+
+// NotSupported returns a *Error indicating "unsupported value".
+// This is used to report unknown values for enumerated fields (e.g. a list of
+// valid values).
+func NotSupported(field *Path, value interface{}, validValues []string) *Error {
+ detail := ""
+ if validValues != nil && len(validValues) > 0 {
+ detail = "supported values: " + strings.Join(validValues, ", ")
+ }
+ return &Error{ErrorTypeNotSupported, field.String(), value, detail}
+}
+
+// Forbidden returns a *Error indicating "forbidden". This is used to
+// report valid (as per formatting rules) values which would be accepted under
+// some conditions, but which are not permitted by current conditions (e.g.
+// security policy).
+func Forbidden(field *Path, detail string) *Error {
+ return &Error{ErrorTypeForbidden, field.String(), "", detail}
+}
+
+// TooLong returns a *Error indicating "too long". This is used to
+// report that the given value is too long. This is similar to
+// Invalid, but the returned error will not include the too-long
+// value.
+func TooLong(field *Path, value interface{}, maxLength int) *Error {
+ return &Error{ErrorTypeTooLong, field.String(), value, fmt.Sprintf("must have at most %d characters", maxLength)}
+}
+
+// InternalError returns a *Error indicating "internal error". This is used
+// to signal that an error was found that was not directly related to user
+// input. The err argument must be non-nil.
+func InternalError(field *Path, err error) *Error {
+ return &Error{ErrorTypeInternal, field.String(), nil, err.Error()}
+}
+
+// ErrorList holds a set of Errors. It is plausible that we might one day have
+// non-field errors in this same umbrella package, but for now we don't, so
+// we can keep it simple and leave ErrorList here.
+type ErrorList []*Error
+
+// NewErrorTypeMatcher returns an errors.Matcher that returns true
+// if the provided error is a Error and has the provided ErrorType.
+func NewErrorTypeMatcher(t ErrorType) utilerrors.Matcher {
+ return func(err error) bool {
+ if e, ok := err.(*Error); ok {
+ return e.Type == t
+ }
+ return false
+ }
+}
+
+// ToAggregate converts the ErrorList into an errors.Aggregate.
+func (list ErrorList) ToAggregate() utilerrors.Aggregate {
+ errs := make([]error, len(list))
+ for i := range list {
+ errs[i] = list[i]
+ }
+ return utilerrors.NewAggregate(errs)
+}
+
+func fromAggregate(agg utilerrors.Aggregate) ErrorList {
+ errs := agg.Errors()
+ list := make(ErrorList, len(errs))
+ for i := range errs {
+ list[i] = errs[i].(*Error)
+ }
+ return list
+}
+
+// Filter removes items from the ErrorList that match the provided fns.
+func (list ErrorList) Filter(fns ...utilerrors.Matcher) ErrorList {
+ err := utilerrors.FilterOut(list.ToAggregate(), fns...)
+ if err == nil {
+ return nil
+ }
+ // FilterOut takes an Aggregate and returns an Aggregate
+ return fromAggregate(err.(utilerrors.Aggregate))
+}
diff --git a/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/validation/field/path.go b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/validation/field/path.go
new file mode 100644
index 0000000..2efc8ee
--- /dev/null
+++ b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/validation/field/path.go
@@ -0,0 +1,91 @@
+/*
+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 field
+
+import (
+ "bytes"
+ "fmt"
+ "strconv"
+)
+
+// Path represents the path from some root to a particular field.
+type Path struct {
+ name string // the name of this field or "" if this is an index
+ index string // if name == "", this is a subscript (index or map key) of the previous element
+ parent *Path // nil if this is the root element
+}
+
+// NewPath creates a root Path object.
+func NewPath(name string, moreNames ...string) *Path {
+ r := &Path{name: name, parent: nil}
+ for _, anotherName := range moreNames {
+ r = &Path{name: anotherName, parent: r}
+ }
+ return r
+}
+
+// Root returns the root element of this Path.
+func (p *Path) Root() *Path {
+ for ; p.parent != nil; p = p.parent {
+ // Do nothing.
+ }
+ return p
+}
+
+// Child creates a new Path that is a child of the method receiver.
+func (p *Path) Child(name string, moreNames ...string) *Path {
+ r := NewPath(name, moreNames...)
+ r.Root().parent = p
+ return r
+}
+
+// Index indicates that the previous Path is to be subscripted by an int.
+// This sets the same underlying value as Key.
+func (p *Path) Index(index int) *Path {
+ return &Path{index: strconv.Itoa(index), parent: p}
+}
+
+// Key indicates that the previous Path is to be subscripted by a string.
+// This sets the same underlying value as Index.
+func (p *Path) Key(key string) *Path {
+ return &Path{index: key, parent: p}
+}
+
+// String produces a string representation of the Path.
+func (p *Path) String() string {
+ // make a slice to iterate
+ elems := []*Path{}
+ for ; p != nil; p = p.parent {
+ elems = append(elems, p)
+ }
+
+ // iterate, but it has to be backwards
+ buf := bytes.NewBuffer(nil)
+ for i := range elems {
+ p := elems[len(elems)-1-i]
+ if p.parent != nil && len(p.name) > 0 {
+ // This is either the root or it is a subscript.
+ buf.WriteString(".")
+ }
+ if len(p.name) > 0 {
+ buf.WriteString(p.name)
+ } else {
+ fmt.Fprintf(buf, "[%s]", p.index)
+ }
+ }
+ return buf.String()
+}
diff --git a/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/validation/validation.go b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/validation/validation.go
new file mode 100644
index 0000000..6e6a027
--- /dev/null
+++ b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/validation/validation.go
@@ -0,0 +1,306 @@
+/*
+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 validation
+
+import (
+ "fmt"
+ "math"
+ "net"
+ "regexp"
+ "strings"
+)
+
+const qnameCharFmt string = "[A-Za-z0-9]"
+const qnameExtCharFmt string = "[-A-Za-z0-9_.]"
+const qualifiedNameFmt string = "(" + qnameCharFmt + qnameExtCharFmt + "*)?" + qnameCharFmt
+const qualifiedNameMaxLength int = 63
+
+var qualifiedNameRegexp = regexp.MustCompile("^" + qualifiedNameFmt + "$")
+
+// IsQualifiedName tests whether the value passed is what Kubernetes calls a
+// "qualified name". This is a format used in various places throughout the
+// system. If the value is not valid, a list of error strings is returned.
+// Otherwise an empty list (or nil) is returned.
+func IsQualifiedName(value string) []string {
+ var errs []string
+ parts := strings.Split(value, "/")
+ var name string
+ switch len(parts) {
+ case 1:
+ name = parts[0]
+ case 2:
+ var prefix string
+ prefix, name = parts[0], parts[1]
+ if len(prefix) == 0 {
+ errs = append(errs, "prefix part "+EmptyError())
+ } else if msgs := IsDNS1123Subdomain(prefix); len(msgs) != 0 {
+ errs = append(errs, prefixEach(msgs, "prefix part ")...)
+ }
+ default:
+ return append(errs, RegexError(qualifiedNameFmt, "MyName", "my.name", "123-abc")+
+ " with an optional DNS subdomain prefix and '/' (e.g. 'example.com/MyName'")
+ }
+
+ if len(name) == 0 {
+ errs = append(errs, "name part "+EmptyError())
+ } else if len(name) > qualifiedNameMaxLength {
+ errs = append(errs, "name part "+MaxLenError(qualifiedNameMaxLength))
+ }
+ if !qualifiedNameRegexp.MatchString(name) {
+ errs = append(errs, "name part "+RegexError(qualifiedNameFmt, "MyName", "my.name", "123-abc"))
+ }
+ return errs
+}
+
+const labelValueFmt string = "(" + qualifiedNameFmt + ")?"
+const LabelValueMaxLength int = 63
+
+var labelValueRegexp = regexp.MustCompile("^" + labelValueFmt + "$")
+
+// IsValidLabelValue tests whether the value passed is a valid label value. If
+// the value is not valid, a list of error strings is returned. Otherwise an
+// empty list (or nil) is returned.
+func IsValidLabelValue(value string) []string {
+ var errs []string
+ if len(value) > LabelValueMaxLength {
+ errs = append(errs, MaxLenError(LabelValueMaxLength))
+ }
+ if !labelValueRegexp.MatchString(value) {
+ errs = append(errs, RegexError(labelValueFmt, "MyValue", "my_value", "12345"))
+ }
+ return errs
+}
+
+const dns1123LabelFmt string = "[a-z0-9]([-a-z0-9]*[a-z0-9])?"
+const DNS1123LabelMaxLength int = 63
+
+var dns1123LabelRegexp = regexp.MustCompile("^" + dns1123LabelFmt + "$")
+
+// IsDNS1123Label tests for a string that conforms to the definition of a label in
+// DNS (RFC 1123).
+func IsDNS1123Label(value string) []string {
+ var errs []string
+ if len(value) > DNS1123LabelMaxLength {
+ errs = append(errs, MaxLenError(DNS1123LabelMaxLength))
+ }
+ if !dns1123LabelRegexp.MatchString(value) {
+ errs = append(errs, RegexError(dns1123LabelFmt, "my-name", "123-abc"))
+ }
+ return errs
+}
+
+const dns1123SubdomainFmt string = dns1123LabelFmt + "(\\." + dns1123LabelFmt + ")*"
+const DNS1123SubdomainMaxLength int = 253
+
+var dns1123SubdomainRegexp = regexp.MustCompile("^" + dns1123SubdomainFmt + "$")
+
+// IsDNS1123Subdomain tests for a string that conforms to the definition of a
+// subdomain in DNS (RFC 1123).
+func IsDNS1123Subdomain(value string) []string {
+ var errs []string
+ if len(value) > DNS1123SubdomainMaxLength {
+ errs = append(errs, MaxLenError(DNS1123SubdomainMaxLength))
+ }
+ if !dns1123SubdomainRegexp.MatchString(value) {
+ errs = append(errs, RegexError(dns1123SubdomainFmt, "example.com"))
+ }
+ return errs
+}
+
+const dns952LabelFmt string = "[a-z]([-a-z0-9]*[a-z0-9])?"
+const DNS952LabelMaxLength int = 24
+
+var dns952LabelRegexp = regexp.MustCompile("^" + dns952LabelFmt + "$")
+
+// IsDNS952Label tests for a string that conforms to the definition of a label in
+// DNS (RFC 952).
+func IsDNS952Label(value string) []string {
+ var errs []string
+ if len(value) > DNS952LabelMaxLength {
+ errs = append(errs, MaxLenError(DNS952LabelMaxLength))
+ }
+ if !dns952LabelRegexp.MatchString(value) {
+ errs = append(errs, RegexError(dns952LabelFmt, "my-name", "abc-123"))
+ }
+ return errs
+}
+
+const cIdentifierFmt string = "[A-Za-z_][A-Za-z0-9_]*"
+
+var cIdentifierRegexp = regexp.MustCompile("^" + cIdentifierFmt + "$")
+
+// IsCIdentifier tests for a string that conforms the definition of an identifier
+// in C. This checks the format, but not the length.
+func IsCIdentifier(value string) []string {
+ if !cIdentifierRegexp.MatchString(value) {
+ return []string{RegexError(cIdentifierFmt, "my_name", "MY_NAME", "MyName")}
+ }
+ return nil
+}
+
+// IsValidPortNum tests that the argument is a valid, non-zero port number.
+func IsValidPortNum(port int) []string {
+ if 1 <= port && port <= 65535 {
+ return nil
+ }
+ return []string{InclusiveRangeError(1, 65535)}
+}
+
+// Now in libcontainer UID/GID limits is 0 ~ 1<<31 - 1
+// TODO: once we have a type for UID/GID we should make these that type.
+const (
+ minUserID = 0
+ maxUserID = math.MaxInt32
+ minGroupID = 0
+ maxGroupID = math.MaxInt32
+)
+
+// IsValidGroupId tests that the argument is a valid Unix GID.
+func IsValidGroupId(gid int64) []string {
+ if minGroupID <= gid && gid <= maxGroupID {
+ return nil
+ }
+ return []string{InclusiveRangeError(minGroupID, maxGroupID)}
+}
+
+// IsValidUserId tests that the argument is a valid Unix UID.
+func IsValidUserId(uid int64) []string {
+ if minUserID <= uid && uid <= maxUserID {
+ return nil
+ }
+ return []string{InclusiveRangeError(minUserID, maxUserID)}
+}
+
+var portNameCharsetRegex = regexp.MustCompile("^[-a-z0-9]+$")
+var portNameOneLetterRegexp = regexp.MustCompile("[a-z]")
+
+// IsValidPortName check that the argument is valid syntax. It must be
+// non-empty and no more than 15 characters long. It may contain only [-a-z0-9]
+// and must contain at least one letter [a-z]. It must not start or end with a
+// hyphen, nor contain adjacent hyphens.
+//
+// Note: We only allow lower-case characters, even though RFC 6335 is case
+// insensitive.
+func IsValidPortName(port string) []string {
+ var errs []string
+ if len(port) > 15 {
+ errs = append(errs, MaxLenError(15))
+ }
+ if !portNameCharsetRegex.MatchString(port) {
+ errs = append(errs, "must contain only alpha-numeric characters (a-z, 0-9), and hyphens (-)")
+ }
+ if !portNameOneLetterRegexp.MatchString(port) {
+ errs = append(errs, "must contain at least one letter (a-z)")
+ }
+ if strings.Contains(port, "--") {
+ errs = append(errs, "must not contain consecutive hyphens")
+ }
+ if len(port) > 0 && (port[0] == '-' || port[len(port)-1] == '-') {
+ errs = append(errs, "must not begin or end with a hyphen")
+ }
+ return errs
+}
+
+// IsValidIP tests that the argument is a valid IP address.
+func IsValidIP(value string) []string {
+ if net.ParseIP(value) == nil {
+ return []string{"must be a valid IP address, (e.g. 10.9.8.7)"}
+ }
+ return nil
+}
+
+const percentFmt string = "[0-9]+%"
+
+var percentRegexp = regexp.MustCompile("^" + percentFmt + "$")
+
+func IsValidPercent(percent string) []string {
+ if !percentRegexp.MatchString(percent) {
+ return []string{RegexError(percentFmt, "1%", "93%")}
+ }
+ return nil
+}
+
+const httpHeaderNameFmt string = "[-A-Za-z0-9]+"
+
+var httpHeaderNameRegexp = regexp.MustCompile("^" + httpHeaderNameFmt + "$")
+
+// IsHTTPHeaderName checks that a string conforms to the Go HTTP library's
+// definition of a valid header field name (a stricter subset than RFC7230).
+func IsHTTPHeaderName(value string) []string {
+ if !httpHeaderNameRegexp.MatchString(value) {
+ return []string{RegexError(httpHeaderNameFmt, "X-Header-Name")}
+ }
+ return nil
+}
+
+const configMapKeyFmt = "\\.?" + dns1123SubdomainFmt
+
+var configMapKeyRegexp = regexp.MustCompile("^" + configMapKeyFmt + "$")
+
+// IsConfigMapKey tests for a string that conforms to the definition of a
+// subdomain in DNS (RFC 1123), except that a leading dot is allowed
+func IsConfigMapKey(value string) []string {
+ var errs []string
+ if len(value) > DNS1123SubdomainMaxLength {
+ errs = append(errs, MaxLenError(DNS1123SubdomainMaxLength))
+ }
+ if !configMapKeyRegexp.MatchString(value) {
+ errs = append(errs, RegexError(configMapKeyFmt, "key.name"))
+ }
+ return errs
+}
+
+// MaxLenError returns a string explanation of a "string too long" validation
+// failure.
+func MaxLenError(length int) string {
+ return fmt.Sprintf("must be no more than %d characters", length)
+}
+
+// RegexError returns a string explanation of a regex validation failure.
+func RegexError(fmt string, examples ...string) string {
+ s := "must match the regex " + fmt
+ if len(examples) == 0 {
+ return s
+ }
+ s += " (e.g. "
+ for i := range examples {
+ if i > 0 {
+ s += " or "
+ }
+ s += "'" + examples[i] + "'"
+ }
+ return s + ")"
+}
+
+// EmptyError returns a string explanation of a "must not be empty" validation
+// failure.
+func EmptyError() string {
+ return "must be non-empty"
+}
+
+func prefixEach(msgs []string, prefix string) []string {
+ for i := range msgs {
+ msgs[i] = prefix + msgs[i]
+ }
+ return msgs
+}
+
+// InclusiveRangeError returns a string explanation of a numeric "must be
+// between" validation failure.
+func InclusiveRangeError(lo, hi int) string {
+ return fmt.Sprintf(`must be between %d and %d, inclusive`, lo, hi)
+}
diff --git a/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/wait/doc.go b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/wait/doc.go
new file mode 100644
index 0000000..ff89dc1
--- /dev/null
+++ b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/wait/doc.go
@@ -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 wait provides tools for polling or listening for changes
+// to a condition.
+package wait
diff --git a/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/wait/wait.go b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/wait/wait.go
new file mode 100644
index 0000000..bd4543e
--- /dev/null
+++ b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/wait/wait.go
@@ -0,0 +1,268 @@
+/*
+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 wait
+
+import (
+ "errors"
+ "math/rand"
+ "time"
+
+ "k8s.io/kubernetes/pkg/util/runtime"
+)
+
+// For any test of the style:
+// ...
+// <- time.After(timeout):
+// t.Errorf("Timed out")
+// The value for timeout should effectively be "forever." Obviously we don't want our tests to truly lock up forever, but 30s
+// is long enough that it is effectively forever for the things that can slow down a run on a heavily contended machine
+// (GC, seeks, etc), but not so long as to make a developer ctrl-c a test run if they do happen to break that test.
+var ForeverTestTimeout = time.Second * 30
+
+// NeverStop may be passed to Until to make it never stop.
+var NeverStop <-chan struct{} = make(chan struct{})
+
+// Forever is syntactic sugar on top of Until
+func Forever(f func(), period time.Duration) {
+ Until(f, period, NeverStop)
+}
+
+// Until loops until stop channel is closed, running f every period.
+// Until is syntactic sugar on top of JitterUntil with zero jitter
+// factor, with sliding = true (which means the timer for period
+// starts after the f completes).
+func Until(f func(), period time.Duration, stopCh <-chan struct{}) {
+ JitterUntil(f, period, 0.0, true, stopCh)
+}
+
+// NonSlidingUntil loops until stop channel is closed, running f every
+// period. NonSlidingUntil is syntactic sugar on top of JitterUntil
+// with zero jitter factor, with sliding = false (meaning the timer for
+// period starts at the same time as the function starts).
+func NonSlidingUntil(f func(), period time.Duration, stopCh <-chan struct{}) {
+ JitterUntil(f, period, 0.0, false, stopCh)
+}
+
+// JitterUntil loops until stop channel is closed, running f every period.
+// If jitterFactor is positive, the period is jittered before every run of f.
+// If jitterFactor is not positive, the period is unchanged.
+// Catches any panics, and keeps going. f may not be invoked if
+// stop channel is already closed. Pass NeverStop to Until if you
+// don't want it stop.
+func JitterUntil(f func(), period time.Duration, jitterFactor float64, sliding bool, stopCh <-chan struct{}) {
+ select {
+ case <-stopCh:
+ return
+ default:
+ }
+
+ for {
+ jitteredPeriod := period
+ if jitterFactor > 0.0 {
+ jitteredPeriod = Jitter(period, jitterFactor)
+ }
+
+ var t *time.Timer
+ if !sliding {
+ t = time.NewTimer(jitteredPeriod)
+ }
+
+ func() {
+ defer runtime.HandleCrash()
+ f()
+ }()
+
+ if sliding {
+ t = time.NewTimer(jitteredPeriod)
+ } else {
+ // The timer we created could already have fired, so be
+ // careful and check stopCh first.
+ select {
+ case <-stopCh:
+ return
+ default:
+ }
+ }
+
+ select {
+ case <-stopCh:
+ return
+ case <-t.C:
+ }
+ }
+}
+
+// Jitter returns a time.Duration between duration and duration + maxFactor * duration,
+// to allow clients to avoid converging on periodic behavior. If maxFactor is 0.0, a
+// suggested default value will be chosen.
+func Jitter(duration time.Duration, maxFactor float64) time.Duration {
+ if maxFactor <= 0.0 {
+ maxFactor = 1.0
+ }
+ wait := duration + time.Duration(rand.Float64()*maxFactor*float64(duration))
+ return wait
+}
+
+// ErrWaitTimeout is returned when the condition exited without success
+var ErrWaitTimeout = errors.New("timed out waiting for the condition")
+
+// ConditionFunc returns true if the condition is satisfied, or an error
+// if the loop should be aborted.
+type ConditionFunc func() (done bool, err error)
+
+// Backoff is parameters applied to a Backoff function.
+type Backoff struct {
+ Duration time.Duration
+ Factor float64
+ Jitter float64
+ Steps int
+}
+
+// ExponentialBackoff repeats a condition check up to steps times, increasing the wait
+// by multipling the previous duration by factor. If jitter is greater than zero,
+// a random amount of each duration is added (between duration and duration*(1+jitter)).
+// If the condition never returns true, ErrWaitTimeout is returned. All other errors
+// terminate immediately.
+func ExponentialBackoff(backoff Backoff, condition ConditionFunc) error {
+ duration := backoff.Duration
+ for i := 0; i < backoff.Steps; i++ {
+ if i != 0 {
+ adjusted := duration
+ if backoff.Jitter > 0.0 {
+ adjusted = Jitter(duration, backoff.Jitter)
+ }
+ time.Sleep(adjusted)
+ duration = time.Duration(float64(duration) * backoff.Factor)
+ }
+ if ok, err := condition(); err != nil || ok {
+ return err
+ }
+ }
+ return ErrWaitTimeout
+}
+
+// Poll tries a condition func until it returns true, an error, or the timeout
+// is reached. condition will always be invoked at least once but some intervals
+// may be missed if the condition takes too long or the time window is too short.
+// If you want to Poll something forever, see PollInfinite.
+// Poll always waits the interval before the first check of the condition.
+func Poll(interval, timeout time.Duration, condition ConditionFunc) error {
+ return pollInternal(poller(interval, timeout), condition)
+}
+
+func pollInternal(wait WaitFunc, condition ConditionFunc) error {
+ done := make(chan struct{})
+ defer close(done)
+ return WaitFor(wait, condition, done)
+}
+
+// PollImmediate is identical to Poll, except that it performs the first check
+// immediately, not waiting interval beforehand.
+func PollImmediate(interval, timeout time.Duration, condition ConditionFunc) error {
+ return pollImmediateInternal(poller(interval, timeout), condition)
+}
+
+func pollImmediateInternal(wait WaitFunc, condition ConditionFunc) error {
+ done, err := condition()
+ if err != nil {
+ return err
+ }
+ if done {
+ return nil
+ }
+ return pollInternal(wait, condition)
+}
+
+// PollInfinite polls forever.
+func PollInfinite(interval time.Duration, condition ConditionFunc) error {
+ done := make(chan struct{})
+ defer close(done)
+ return WaitFor(poller(interval, 0), condition, done)
+}
+
+// WaitFunc creates a channel that receives an item every time a test
+// should be executed and is closed when the last test should be invoked.
+type WaitFunc func(done <-chan struct{}) <-chan struct{}
+
+// WaitFor gets a channel from wait(), and then invokes fn once for every value
+// placed on the channel and once more when the channel is closed. If fn
+// returns an error the loop ends and that error is returned, and if fn returns
+// true the loop ends and nil is returned. ErrWaitTimeout will be returned if
+// the channel is closed without fn ever returning true.
+func WaitFor(wait WaitFunc, fn ConditionFunc, done <-chan struct{}) error {
+ c := wait(done)
+ for {
+ _, open := <-c
+ ok, err := fn()
+ if err != nil {
+ return err
+ }
+ if ok {
+ return nil
+ }
+ if !open {
+ break
+ }
+ }
+ return ErrWaitTimeout
+}
+
+// poller returns a WaitFunc that will send to the channel every
+// interval until timeout has elapsed and then close the channel.
+// Over very short intervals you may receive no ticks before
+// the channel is closed. If timeout is 0, the channel
+// will never be closed.
+func poller(interval, timeout time.Duration) WaitFunc {
+ return WaitFunc(func(done <-chan struct{}) <-chan struct{} {
+ ch := make(chan struct{})
+
+ go func() {
+ defer close(ch)
+
+ tick := time.NewTicker(interval)
+ defer tick.Stop()
+
+ var after <-chan time.Time
+ if timeout != 0 {
+ // time.After is more convenient, but it
+ // potentially leaves timers around much longer
+ // than necessary if we exit early.
+ timer := time.NewTimer(timeout)
+ after = timer.C
+ defer timer.Stop()
+ }
+
+ for {
+ select {
+ case <-tick.C:
+ // If the consumer isn't ready for this signal drop it and
+ // check the other channels.
+ select {
+ case ch <- struct{}{}:
+ default:
+ }
+ case <-after:
+ return
+ case <-done:
+ return
+ }
+ }
+ }()
+
+ return ch
+ })
+}
diff --git a/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/yaml/decoder.go b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/yaml/decoder.go
new file mode 100644
index 0000000..6a9f05a
--- /dev/null
+++ b/kube2msb/src/kube2msb/vendor/k8s.io/kubernetes/pkg/util/yaml/decoder.go
@@ -0,0 +1,247 @@
+/*
+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 yaml
+
+import (
+ "bufio"
+ "bytes"
+ "encoding/json"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "strings"
+ "unicode"
+
+ "github.com/ghodss/yaml"
+ "github.com/golang/glog"
+)
+
+// ToJSON converts a single YAML document into a JSON document
+// or returns an error. If the document appears to be JSON the
+// YAML decoding path is not used (so that error messages are
+// JSON specific).
+func ToJSON(data []byte) ([]byte, error) {
+ if hasJSONPrefix(data) {
+ return data, nil
+ }
+ return yaml.YAMLToJSON(data)
+}
+
+// YAMLToJSONDecoder decodes YAML documents from an io.Reader by
+// separating individual documents. It first converts the YAML
+// body to JSON, then unmarshals the JSON.
+type YAMLToJSONDecoder struct {
+ scanner *bufio.Scanner
+}
+
+// NewYAMLToJSONDecoder decodes YAML documents from the provided
+// stream in chunks by converting each document (as defined by
+// the YAML spec) into its own chunk, converting it to JSON via
+// yaml.YAMLToJSON, and then passing it to json.Decoder.
+func NewYAMLToJSONDecoder(r io.Reader) *YAMLToJSONDecoder {
+ scanner := bufio.NewScanner(r)
+ scanner.Split(splitYAMLDocument)
+ return &YAMLToJSONDecoder{
+ scanner: scanner,
+ }
+}
+
+// Decode reads a YAML document as JSON from the stream or returns
+// an error. The decoding rules match json.Unmarshal, not
+// yaml.Unmarshal.
+func (d *YAMLToJSONDecoder) Decode(into interface{}) error {
+ if d.scanner.Scan() {
+ data, err := yaml.YAMLToJSON(d.scanner.Bytes())
+ if err != nil {
+ return err
+ }
+ return json.Unmarshal(data, into)
+ }
+ err := d.scanner.Err()
+ if err == nil {
+ err = io.EOF
+ }
+ return err
+}
+
+// YAMLDecoder reads chunks of objects and returns ErrShortBuffer if
+// the data is not sufficient.
+type YAMLDecoder struct {
+ r io.ReadCloser
+ scanner *bufio.Scanner
+ remaining []byte
+}
+
+// NewDocumentDecoder decodes YAML documents from the provided
+// stream in chunks by converting each document (as defined by
+// the YAML spec) into its own chunk. io.ErrShortBuffer will be
+// returned if the entire buffer could not be read to assist
+// the caller in framing the chunk.
+func NewDocumentDecoder(r io.ReadCloser) io.ReadCloser {
+ scanner := bufio.NewScanner(r)
+ scanner.Split(splitYAMLDocument)
+ return &YAMLDecoder{
+ r: r,
+ scanner: scanner,
+ }
+}
+
+// Read reads the previous slice into the buffer, or attempts to read
+// the next chunk.
+// TODO: switch to readline approach.
+func (d *YAMLDecoder) Read(data []byte) (n int, err error) {
+ left := len(d.remaining)
+ if left == 0 {
+ // return the next chunk from the stream
+ if !d.scanner.Scan() {
+ err := d.scanner.Err()
+ if err == nil {
+ err = io.EOF
+ }
+ return 0, err
+ }
+ out := d.scanner.Bytes()
+ d.remaining = out
+ left = len(out)
+ }
+
+ // fits within data
+ if left <= len(data) {
+ copy(data, d.remaining)
+ d.remaining = nil
+ return len(d.remaining), nil
+ }
+
+ // caller will need to reread
+ copy(data, d.remaining[:left])
+ d.remaining = d.remaining[left:]
+ return len(data), io.ErrShortBuffer
+}
+
+func (d *YAMLDecoder) Close() error {
+ return d.r.Close()
+}
+
+const yamlSeparator = "\n---"
+
+// splitYAMLDocument is a bufio.SplitFunc for splitting YAML streams into individual documents.
+func splitYAMLDocument(data []byte, atEOF bool) (advance int, token []byte, err error) {
+ if atEOF && len(data) == 0 {
+ return 0, nil, nil
+ }
+ sep := len([]byte(yamlSeparator))
+ if i := bytes.Index(data, []byte(yamlSeparator)); i >= 0 {
+ // We have a potential document terminator
+ i += sep
+ after := data[i:]
+ if len(after) == 0 {
+ // we can't read any more characters
+ if atEOF {
+ return len(data), data[:len(data)-sep], nil
+ }
+ return 0, nil, nil
+ }
+ if j := bytes.IndexByte(after, '\n'); j >= 0 {
+ return i + j + 1, data[0 : i-sep], nil
+ }
+ return 0, nil, nil
+ }
+ // If we're at EOF, we have a final, non-terminated line. Return it.
+ if atEOF {
+ return len(data), data, nil
+ }
+ // Request more data.
+ return 0, nil, nil
+}
+
+// decoder is a convenience interface for Decode.
+type decoder interface {
+ Decode(into interface{}) error
+}
+
+// YAMLOrJSONDecoder attempts to decode a stream of JSON documents or
+// YAML documents by sniffing for a leading { character.
+type YAMLOrJSONDecoder struct {
+ r io.Reader
+ bufferSize int
+
+ decoder decoder
+}
+
+// NewYAMLOrJSONDecoder returns a decoder that will process YAML documents
+// or JSON documents from the given reader as a stream. bufferSize determines
+// how far into the stream the decoder will look to figure out whether this
+// is a JSON stream (has whitespace followed by an open brace).
+func NewYAMLOrJSONDecoder(r io.Reader, bufferSize int) *YAMLOrJSONDecoder {
+ return &YAMLOrJSONDecoder{
+ r: r,
+ bufferSize: bufferSize,
+ }
+}
+
+// Decode unmarshals the next object from the underlying stream into the
+// provide object, or returns an error.
+func (d *YAMLOrJSONDecoder) Decode(into interface{}) error {
+ if d.decoder == nil {
+ buffer, isJSON := GuessJSONStream(d.r, d.bufferSize)
+ if isJSON {
+ glog.V(4).Infof("decoding stream as JSON")
+ d.decoder = json.NewDecoder(buffer)
+ } else {
+ glog.V(4).Infof("decoding stream as YAML")
+ d.decoder = NewYAMLToJSONDecoder(buffer)
+ }
+ }
+ err := d.decoder.Decode(into)
+ if jsonDecoder, ok := d.decoder.(*json.Decoder); ok {
+ if syntax, ok := err.(*json.SyntaxError); ok {
+ data, readErr := ioutil.ReadAll(jsonDecoder.Buffered())
+ if readErr != nil {
+ glog.V(4).Infof("reading stream failed: %v", readErr)
+ }
+ js := string(data)
+ start := strings.LastIndex(js[:syntax.Offset], "\n") + 1
+ line := strings.Count(js[:start], "\n")
+ return fmt.Errorf("json: line %d: %s", line, syntax.Error())
+ }
+ }
+ return err
+}
+
+// GuessJSONStream scans the provided reader up to size, looking
+// for an open brace indicating this is JSON. It will return the
+// bufio.Reader it creates for the consumer.
+func GuessJSONStream(r io.Reader, size int) (io.Reader, bool) {
+ buffer := bufio.NewReaderSize(r, size)
+ b, _ := buffer.Peek(size)
+ return buffer, hasJSONPrefix(b)
+}
+
+var jsonPrefix = []byte("{")
+
+// hasJSONPrefix returns true if the provided buffer appears to start with
+// a JSON open brace.
+func hasJSONPrefix(buf []byte) bool {
+ return hasPrefix(buf, jsonPrefix)
+}
+
+// Return true if the first non-whitespace bytes in buf is
+// prefix.
+func hasPrefix(buf []byte, prefix []byte) bool {
+ trim := bytes.TrimLeftFunc(buf, unicode.IsSpace)
+ return bytes.HasPrefix(trim, prefix)
+}