git subrepo clone (merge) https://github.com/kubernetes-incubator/metrics-server.git metrics-server

subrepo:
  subdir:   "metrics-server"
  merged:   "92d8412"
upstream:
  origin:   "https://github.com/kubernetes-incubator/metrics-server.git"
  branch:   "master"
  commit:   "92d8412"
git-subrepo:
  version:  "0.4.0"
  origin:   "???"
  commit:   "???"
diff --git a/metrics-server/vendor/github.com/evanphx/json-patch/patch.go b/metrics-server/vendor/github.com/evanphx/json-patch/patch.go
new file mode 100644
index 0000000..755d8ba
--- /dev/null
+++ b/metrics-server/vendor/github.com/evanphx/json-patch/patch.go
@@ -0,0 +1,663 @@
+package jsonpatch
+
+import (
+	"bytes"
+	"encoding/json"
+	"fmt"
+	"strconv"
+	"strings"
+)
+
+const (
+	eRaw = iota
+	eDoc
+	eAry
+)
+
+type lazyNode struct {
+	raw   *json.RawMessage
+	doc   partialDoc
+	ary   partialArray
+	which int
+}
+
+type operation map[string]*json.RawMessage
+
+// Patch is an ordered collection of operations.
+type Patch []operation
+
+type partialDoc map[string]*lazyNode
+type partialArray []*lazyNode
+
+type container interface {
+	get(key string) (*lazyNode, error)
+	set(key string, val *lazyNode) error
+	add(key string, val *lazyNode) error
+	remove(key string) error
+}
+
+func newLazyNode(raw *json.RawMessage) *lazyNode {
+	return &lazyNode{raw: raw, doc: nil, ary: nil, which: eRaw}
+}
+
+func (n *lazyNode) MarshalJSON() ([]byte, error) {
+	switch n.which {
+	case eRaw:
+		return json.Marshal(n.raw)
+	case eDoc:
+		return json.Marshal(n.doc)
+	case eAry:
+		return json.Marshal(n.ary)
+	default:
+		return nil, fmt.Errorf("Unknown type")
+	}
+}
+
+func (n *lazyNode) UnmarshalJSON(data []byte) error {
+	dest := make(json.RawMessage, len(data))
+	copy(dest, data)
+	n.raw = &dest
+	n.which = eRaw
+	return nil
+}
+
+func (n *lazyNode) intoDoc() (*partialDoc, error) {
+	if n.which == eDoc {
+		return &n.doc, nil
+	}
+
+	if n.raw == nil {
+		return nil, fmt.Errorf("Unable to unmarshal nil pointer as partial document")
+	}
+
+	err := json.Unmarshal(*n.raw, &n.doc)
+
+	if err != nil {
+		return nil, err
+	}
+
+	n.which = eDoc
+	return &n.doc, nil
+}
+
+func (n *lazyNode) intoAry() (*partialArray, error) {
+	if n.which == eAry {
+		return &n.ary, nil
+	}
+
+	if n.raw == nil {
+		return nil, fmt.Errorf("Unable to unmarshal nil pointer as partial array")
+	}
+
+	err := json.Unmarshal(*n.raw, &n.ary)
+
+	if err != nil {
+		return nil, err
+	}
+
+	n.which = eAry
+	return &n.ary, nil
+}
+
+func (n *lazyNode) compact() []byte {
+	buf := &bytes.Buffer{}
+
+	if n.raw == nil {
+		return nil
+	}
+
+	err := json.Compact(buf, *n.raw)
+
+	if err != nil {
+		return *n.raw
+	}
+
+	return buf.Bytes()
+}
+
+func (n *lazyNode) tryDoc() bool {
+	if n.raw == nil {
+		return false
+	}
+
+	err := json.Unmarshal(*n.raw, &n.doc)
+
+	if err != nil {
+		return false
+	}
+
+	n.which = eDoc
+	return true
+}
+
+func (n *lazyNode) tryAry() bool {
+	if n.raw == nil {
+		return false
+	}
+
+	err := json.Unmarshal(*n.raw, &n.ary)
+
+	if err != nil {
+		return false
+	}
+
+	n.which = eAry
+	return true
+}
+
+func (n *lazyNode) equal(o *lazyNode) bool {
+	if n.which == eRaw {
+		if !n.tryDoc() && !n.tryAry() {
+			if o.which != eRaw {
+				return false
+			}
+
+			return bytes.Equal(n.compact(), o.compact())
+		}
+	}
+
+	if n.which == eDoc {
+		if o.which == eRaw {
+			if !o.tryDoc() {
+				return false
+			}
+		}
+
+		if o.which != eDoc {
+			return false
+		}
+
+		for k, v := range n.doc {
+			ov, ok := o.doc[k]
+
+			if !ok {
+				return false
+			}
+
+			if v == nil && ov == nil {
+				continue
+			}
+
+			if !v.equal(ov) {
+				return false
+			}
+		}
+
+		return true
+	}
+
+	if o.which != eAry && !o.tryAry() {
+		return false
+	}
+
+	if len(n.ary) != len(o.ary) {
+		return false
+	}
+
+	for idx, val := range n.ary {
+		if !val.equal(o.ary[idx]) {
+			return false
+		}
+	}
+
+	return true
+}
+
+func (o operation) kind() string {
+	if obj, ok := o["op"]; ok {
+		var op string
+
+		err := json.Unmarshal(*obj, &op)
+
+		if err != nil {
+			return "unknown"
+		}
+
+		return op
+	}
+
+	return "unknown"
+}
+
+func (o operation) path() string {
+	if obj, ok := o["path"]; ok {
+		var op string
+
+		err := json.Unmarshal(*obj, &op)
+
+		if err != nil {
+			return "unknown"
+		}
+
+		return op
+	}
+
+	return "unknown"
+}
+
+func (o operation) from() string {
+	if obj, ok := o["from"]; ok {
+		var op string
+
+		err := json.Unmarshal(*obj, &op)
+
+		if err != nil {
+			return "unknown"
+		}
+
+		return op
+	}
+
+	return "unknown"
+}
+
+func (o operation) value() *lazyNode {
+	if obj, ok := o["value"]; ok {
+		return newLazyNode(obj)
+	}
+
+	return nil
+}
+
+func isArray(buf []byte) bool {
+Loop:
+	for _, c := range buf {
+		switch c {
+		case ' ':
+		case '\n':
+		case '\t':
+			continue
+		case '[':
+			return true
+		default:
+			break Loop
+		}
+	}
+
+	return false
+}
+
+func findObject(pd *container, path string) (container, string) {
+	doc := *pd
+
+	split := strings.Split(path, "/")
+
+	if len(split) < 2 {
+		return nil, ""
+	}
+
+	parts := split[1 : len(split)-1]
+
+	key := split[len(split)-1]
+
+	var err error
+
+	for _, part := range parts {
+
+		next, ok := doc.get(decodePatchKey(part))
+
+		if next == nil || ok != nil {
+			return nil, ""
+		}
+
+		if isArray(*next.raw) {
+			doc, err = next.intoAry()
+
+			if err != nil {
+				return nil, ""
+			}
+		} else {
+			doc, err = next.intoDoc()
+
+			if err != nil {
+				return nil, ""
+			}
+		}
+	}
+
+	return doc, decodePatchKey(key)
+}
+
+func (d *partialDoc) set(key string, val *lazyNode) error {
+	(*d)[key] = val
+	return nil
+}
+
+func (d *partialDoc) add(key string, val *lazyNode) error {
+	(*d)[key] = val
+	return nil
+}
+
+func (d *partialDoc) get(key string) (*lazyNode, error) {
+	return (*d)[key], nil
+}
+
+func (d *partialDoc) remove(key string) error {
+	_, ok := (*d)[key]
+	if !ok {
+		return fmt.Errorf("Unable to remove nonexistent key: %s", key)
+	}
+
+	delete(*d, key)
+	return nil
+}
+
+func (d *partialArray) set(key string, val *lazyNode) error {
+	if key == "-" {
+		*d = append(*d, val)
+		return nil
+	}
+
+	idx, err := strconv.Atoi(key)
+	if err != nil {
+		return err
+	}
+
+	sz := len(*d)
+	if idx+1 > sz {
+		sz = idx + 1
+	}
+
+	ary := make([]*lazyNode, sz)
+
+	cur := *d
+
+	copy(ary, cur)
+
+	if idx >= len(ary) {
+		return fmt.Errorf("Unable to access invalid index: %d", idx)
+	}
+
+	ary[idx] = val
+
+	*d = ary
+	return nil
+}
+
+func (d *partialArray) add(key string, val *lazyNode) error {
+	if key == "-" {
+		*d = append(*d, val)
+		return nil
+	}
+
+	idx, err := strconv.Atoi(key)
+	if err != nil {
+		return err
+	}
+
+	ary := make([]*lazyNode, len(*d)+1)
+
+	cur := *d
+
+	if idx < 0 {
+		idx *= -1
+
+		if idx > len(ary) {
+			return fmt.Errorf("Unable to access invalid index: %d", idx)
+		}
+		idx = len(ary) - idx
+	}
+
+	copy(ary[0:idx], cur[0:idx])
+	ary[idx] = val
+	copy(ary[idx+1:], cur[idx:])
+
+	*d = ary
+	return nil
+}
+
+func (d *partialArray) get(key string) (*lazyNode, error) {
+	idx, err := strconv.Atoi(key)
+
+	if err != nil {
+		return nil, err
+	}
+
+	if idx >= len(*d) {
+		return nil, fmt.Errorf("Unable to access invalid index: %d", idx)
+	}
+
+	return (*d)[idx], nil
+}
+
+func (d *partialArray) remove(key string) error {
+	idx, err := strconv.Atoi(key)
+	if err != nil {
+		return err
+	}
+
+	cur := *d
+
+	if idx >= len(cur) {
+		return fmt.Errorf("Unable to remove invalid index: %d", idx)
+	}
+
+	ary := make([]*lazyNode, len(cur)-1)
+
+	copy(ary[0:idx], cur[0:idx])
+	copy(ary[idx:], cur[idx+1:])
+
+	*d = ary
+	return nil
+
+}
+
+func (p Patch) add(doc *container, op operation) error {
+	path := op.path()
+
+	con, key := findObject(doc, path)
+
+	if con == nil {
+		return fmt.Errorf("jsonpatch add operation does not apply: doc is missing path: %s", path)
+	}
+
+	return con.add(key, op.value())
+}
+
+func (p Patch) remove(doc *container, op operation) error {
+	path := op.path()
+
+	con, key := findObject(doc, path)
+
+	if con == nil {
+		return fmt.Errorf("jsonpatch remove operation does not apply: doc is missing path: %s", path)
+	}
+
+	return con.remove(key)
+}
+
+func (p Patch) replace(doc *container, op operation) error {
+	path := op.path()
+
+	con, key := findObject(doc, path)
+
+	if con == nil {
+		return fmt.Errorf("jsonpatch replace operation does not apply: doc is missing path: %s", path)
+	}
+
+	val, ok := con.get(key)
+	if val == nil || ok != nil {
+		return fmt.Errorf("jsonpatch replace operation does not apply: doc is missing key: %s", path)
+	}
+
+	return con.set(key, op.value())
+}
+
+func (p Patch) move(doc *container, op operation) error {
+	from := op.from()
+
+	con, key := findObject(doc, from)
+
+	if con == nil {
+		return fmt.Errorf("jsonpatch move operation does not apply: doc is missing from path: %s", from)
+	}
+
+	val, err := con.get(key)
+	if err != nil {
+		return err
+	}
+
+	err = con.remove(key)
+	if err != nil {
+		return err
+	}
+
+	path := op.path()
+
+	con, key = findObject(doc, path)
+
+	if con == nil {
+		return fmt.Errorf("jsonpatch move operation does not apply: doc is missing destination path: %s", path)
+	}
+
+	return con.set(key, val)
+}
+
+func (p Patch) test(doc *container, op operation) error {
+	path := op.path()
+
+	con, key := findObject(doc, path)
+
+	if con == nil {
+		return fmt.Errorf("jsonpatch test operation does not apply: is missing path: %s", path)
+	}
+
+	val, err := con.get(key)
+
+	if err != nil {
+		return err
+	}
+
+	if val == nil {
+		if op.value().raw == nil {
+			return nil
+		}
+		return fmt.Errorf("Testing value %s failed", path)
+	}
+
+	if val.equal(op.value()) {
+		return nil
+	}
+
+	return fmt.Errorf("Testing value %s failed", path)
+}
+
+func (p Patch) copy(doc *container, op operation) error {
+	from := op.from()
+
+	con, key := findObject(doc, from)
+
+	if con == nil {
+		return fmt.Errorf("jsonpatch copy operation does not apply: doc is missing from path: %s", from)
+	}
+
+	val, err := con.get(key)
+	if err != nil {
+		return err
+	}
+
+	path := op.path()
+
+	con, key = findObject(doc, path)
+
+	if con == nil {
+		return fmt.Errorf("jsonpatch copy operation does not apply: doc is missing destination path: %s", path)
+	}
+
+	return con.set(key, val)
+}
+
+// Equal indicates if 2 JSON documents have the same structural equality.
+func Equal(a, b []byte) bool {
+	ra := make(json.RawMessage, len(a))
+	copy(ra, a)
+	la := newLazyNode(&ra)
+
+	rb := make(json.RawMessage, len(b))
+	copy(rb, b)
+	lb := newLazyNode(&rb)
+
+	return la.equal(lb)
+}
+
+// DecodePatch decodes the passed JSON document as an RFC 6902 patch.
+func DecodePatch(buf []byte) (Patch, error) {
+	var p Patch
+
+	err := json.Unmarshal(buf, &p)
+
+	if err != nil {
+		return nil, err
+	}
+
+	return p, nil
+}
+
+// Apply mutates a JSON document according to the patch, and returns the new
+// document.
+func (p Patch) Apply(doc []byte) ([]byte, error) {
+	return p.ApplyIndent(doc, "")
+}
+
+// ApplyIndent mutates a JSON document according to the patch, and returns the new
+// document indented.
+func (p Patch) ApplyIndent(doc []byte, indent string) ([]byte, error) {
+	var pd container
+	if doc[0] == '[' {
+		pd = &partialArray{}
+	} else {
+		pd = &partialDoc{}
+	}
+
+	err := json.Unmarshal(doc, pd)
+
+	if err != nil {
+		return nil, err
+	}
+
+	err = nil
+
+	for _, op := range p {
+		switch op.kind() {
+		case "add":
+			err = p.add(&pd, op)
+		case "remove":
+			err = p.remove(&pd, op)
+		case "replace":
+			err = p.replace(&pd, op)
+		case "move":
+			err = p.move(&pd, op)
+		case "test":
+			err = p.test(&pd, op)
+		case "copy":
+			err = p.copy(&pd, op)
+		default:
+			err = fmt.Errorf("Unexpected kind: %s", op.kind())
+		}
+
+		if err != nil {
+			return nil, err
+		}
+	}
+
+	if indent != "" {
+		return json.MarshalIndent(pd, "", indent)
+	}
+
+	return json.Marshal(pd)
+}
+
+// From http://tools.ietf.org/html/rfc6901#section-4 :
+//
+// Evaluation of each reference token begins by decoding any escaped
+// character sequence.  This is performed by first transforming any
+// occurrence of the sequence '~1' to '/', and then transforming any
+// occurrence of the sequence '~0' to '~'.
+
+var (
+	rfc6901Decoder = strings.NewReplacer("~1", "/", "~0", "~")
+)
+
+func decodePatchKey(k string) string {
+	return rfc6901Decoder.Replace(k)
+}