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/emicklei/go-restful/.gitignore b/metrics-server/vendor/github.com/emicklei/go-restful/.gitignore
new file mode 100644
index 0000000..cece7be
--- /dev/null
+++ b/metrics-server/vendor/github.com/emicklei/go-restful/.gitignore
@@ -0,0 +1,70 @@
+# Compiled Object files, Static and Dynamic libs (Shared Objects)
+*.o
+*.a
+*.so
+
+# Folders
+_obj
+_test
+
+# Architecture specific extensions/prefixes
+*.[568vq]
+[568vq].out
+
+*.cgo1.go
+*.cgo2.c
+_cgo_defun.c
+_cgo_gotypes.go
+_cgo_export.*
+
+_testmain.go
+
+*.exe
+
+restful.html
+
+*.out
+
+tmp.prof
+
+go-restful.test
+
+examples/restful-basic-authentication
+
+examples/restful-encoding-filter
+
+examples/restful-filters
+
+examples/restful-hello-world
+
+examples/restful-resource-functions
+
+examples/restful-serve-static
+
+examples/restful-user-service
+
+*.DS_Store
+examples/restful-user-resource
+
+examples/restful-multi-containers
+
+examples/restful-form-handling
+
+examples/restful-CORS-filter
+
+examples/restful-options-filter
+
+examples/restful-curly-router
+
+examples/restful-cpuprofiler-service
+
+examples/restful-pre-post-filters
+
+curly.prof
+
+examples/restful-NCSA-logging
+
+examples/restful-html-template
+
+s.html
+restful-path-tail
diff --git a/metrics-server/vendor/github.com/emicklei/go-restful/.travis.yml b/metrics-server/vendor/github.com/emicklei/go-restful/.travis.yml
new file mode 100644
index 0000000..b22f8f5
--- /dev/null
+++ b/metrics-server/vendor/github.com/emicklei/go-restful/.travis.yml
@@ -0,0 +1,6 @@
+language: go
+
+go:
+  - 1.x
+
+script: go test -v
\ No newline at end of file
diff --git a/metrics-server/vendor/github.com/emicklei/go-restful/CHANGES.md b/metrics-server/vendor/github.com/emicklei/go-restful/CHANGES.md
new file mode 100644
index 0000000..195449f
--- /dev/null
+++ b/metrics-server/vendor/github.com/emicklei/go-restful/CHANGES.md
@@ -0,0 +1,242 @@
+Change history of go-restful
+=
+v2.8.0
+- add Request.QueryParameters()
+- add json-iterator (via build tag)
+- disable vgo module (until log is moved)
+
+v2.7.1
+- add vgo module
+
+v2.6.1
+- add JSONNewDecoderFunc to allow custom JSON Decoder usage (go 1.10+)
+
+v2.6.0
+- Make JSR 311 routing and path param processing consistent
+- Adding description to RouteBuilder.Reads()
+- Update example for Swagger12 and OpenAPI
+
+2017-09-13
+- added route condition functions using `.If(func)` in route building.
+
+2017-02-16
+- solved issue #304, make operation names unique
+
+2017-01-30
+ 
+	[IMPORTANT] For swagger users, change your import statement to:	
+	swagger "github.com/emicklei/go-restful-swagger12"
+
+- moved swagger 1.2 code to go-restful-swagger12
+- created TAG 2.0.0
+
+2017-01-27
+
+- remove defer request body close
+- expose Dispatch for testing filters and Routefunctions
+- swagger response model cannot be array 
+- created TAG 1.0.0
+
+2016-12-22
+
+- (API change) Remove code related to caching request content. Removes SetCacheReadEntity(doCache bool)
+
+2016-11-26
+
+- Default change! now use CurlyRouter (was RouterJSR311)
+- Default change! no more caching of request content
+- Default change! do not recover from panics
+
+2016-09-22
+
+- fix the DefaultRequestContentType feature
+
+2016-02-14
+
+- take the qualify factor of the Accept header mediatype into account when deciding the contentype of the response
+- add constructors for custom entity accessors for xml and json 
+
+2015-09-27
+
+- rename new WriteStatusAnd... to WriteHeaderAnd... for consistency
+
+2015-09-25
+
+- fixed problem with changing Header after WriteHeader (issue 235)
+
+2015-09-14
+
+- changed behavior of WriteHeader (immediate write) and WriteEntity (no status write)
+- added support for custom EntityReaderWriters.
+
+2015-08-06
+
+- add support for reading entities from compressed request content
+- use sync.Pool for compressors of http response and request body
+- add Description to Parameter for documentation in Swagger UI
+
+2015-03-20
+
+- add configurable logging
+
+2015-03-18
+
+- if not specified, the Operation is derived from the Route function
+
+2015-03-17
+
+- expose Parameter creation functions
+- make trace logger an interface
+- fix OPTIONSFilter
+- customize rendering of ServiceError
+- JSR311 router now handles wildcards
+- add Notes to Route
+
+2014-11-27
+
+- (api add) PrettyPrint per response. (as proposed in #167)
+
+2014-11-12
+
+- (api add) ApiVersion(.) for documentation in Swagger UI
+
+2014-11-10
+
+- (api change) struct fields tagged with "description" show up in Swagger UI
+
+2014-10-31
+
+- (api change) ReturnsError -> Returns
+- (api add)    RouteBuilder.Do(aBuilder) for DRY use of RouteBuilder
+- fix swagger nested structs
+- sort Swagger response messages by code
+
+2014-10-23
+
+- (api add) ReturnsError allows you to document Http codes in swagger
+- fixed problem with greedy CurlyRouter
+- (api add) Access-Control-Max-Age in CORS
+- add tracing functionality (injectable) for debugging purposes
+- support JSON parse 64bit int 
+- fix empty parameters for swagger
+- WebServicesUrl is now optional for swagger
+- fixed duplicate AccessControlAllowOrigin in CORS
+- (api change) expose ServeMux in container
+- (api add) added AllowedDomains in CORS
+- (api add) ParameterNamed for detailed documentation
+
+2014-04-16
+
+- (api add) expose constructor of Request for testing.
+
+2014-06-27
+
+- (api add) ParameterNamed gives access to a Parameter definition and its data (for further specification).
+- (api add) SetCacheReadEntity allow scontrol over whether or not the request body is being cached (default true for compatibility reasons).
+
+2014-07-03
+
+- (api add) CORS can be configured with a list of allowed domains
+
+2014-03-12
+
+- (api add) Route path parameters can use wildcard or regular expressions. (requires CurlyRouter)
+
+2014-02-26
+
+- (api add) Request now provides information about the matched Route, see method SelectedRoutePath 
+
+2014-02-17
+
+- (api change) renamed parameter constants (go-lint checks)
+
+2014-01-10
+
+- (api add) support for CloseNotify, see http://golang.org/pkg/net/http/#CloseNotifier
+
+2014-01-07
+
+- (api change) Write* methods in Response now return the error or nil.
+- added example of serving HTML from a Go template.
+- fixed comparing Allowed headers in CORS (is now case-insensitive)
+
+2013-11-13
+
+- (api add) Response knows how many bytes are written to the response body.
+
+2013-10-29
+
+- (api add) RecoverHandler(handler RecoverHandleFunction) to change how panic recovery is handled. Default behavior is to log and return a stacktrace. This may be a security issue as it exposes sourcecode information.
+
+2013-10-04
+
+- (api add) Response knows what HTTP status has been written
+- (api add) Request can have attributes (map of string->interface, also called request-scoped variables
+
+2013-09-12
+
+- (api change) Router interface simplified
+- Implemented CurlyRouter, a Router that does not use|allow regular expressions in paths
+
+2013-08-05
+ - add OPTIONS support
+ - add CORS support
+
+2013-08-27
+
+- fixed some reported issues (see github)
+- (api change) deprecated use of WriteError; use WriteErrorString instead
+
+2014-04-15
+
+- (fix) v1.0.1 tag: fix Issue 111: WriteErrorString
+
+2013-08-08
+
+- (api add) Added implementation Container: a WebServices collection with its own http.ServeMux allowing multiple endpoints per program. Existing uses of go-restful will register their services to the DefaultContainer.
+- (api add) the swagger package has be extended to have a UI per container.
+- if panic is detected then a small stack trace is printed (thanks to runner-mei)
+- (api add) WriteErrorString to Response
+
+Important API changes:
+
+- (api remove) package variable DoNotRecover no longer works ; use restful.DefaultContainer.DoNotRecover(true) instead.
+- (api remove) package variable EnableContentEncoding no longer works ; use restful.DefaultContainer.EnableContentEncoding(true) instead.
+ 
+ 
+2013-07-06
+
+- (api add) Added support for response encoding (gzip and deflate(zlib)). This feature is disabled on default (for backwards compatibility). Use restful.EnableContentEncoding = true in your initialization to enable this feature.
+
+2013-06-19
+
+- (improve) DoNotRecover option, moved request body closer, improved ReadEntity
+
+2013-06-03
+
+- (api change) removed Dispatcher interface, hide PathExpression
+- changed receiver names of type functions to be more idiomatic Go
+
+2013-06-02
+
+- (optimize) Cache the RegExp compilation of Paths.
+
+2013-05-22
+	
+- (api add) Added support for request/response filter functions
+
+2013-05-18
+
+
+- (api add) Added feature to change the default Http Request Dispatch function (travis cline)
+- (api change) Moved Swagger Webservice to swagger package (see example restful-user)
+
+[2012-11-14 .. 2013-05-18>
+ 
+- See https://github.com/emicklei/go-restful/commits
+
+2012-11-14
+
+- Initial commit
+
+
diff --git a/metrics-server/vendor/github.com/emicklei/go-restful/LICENSE b/metrics-server/vendor/github.com/emicklei/go-restful/LICENSE
new file mode 100644
index 0000000..ece7ec6
--- /dev/null
+++ b/metrics-server/vendor/github.com/emicklei/go-restful/LICENSE
@@ -0,0 +1,22 @@
+Copyright (c) 2012,2013 Ernest Micklei
+
+MIT License
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\ No newline at end of file
diff --git a/metrics-server/vendor/github.com/emicklei/go-restful/Makefile b/metrics-server/vendor/github.com/emicklei/go-restful/Makefile
new file mode 100644
index 0000000..b40081c
--- /dev/null
+++ b/metrics-server/vendor/github.com/emicklei/go-restful/Makefile
@@ -0,0 +1,7 @@
+all: test
+
+test:
+	go test -v .
+
+ex:
+	cd examples && ls *.go | xargs go build -o /tmp/ignore
\ No newline at end of file
diff --git a/metrics-server/vendor/github.com/emicklei/go-restful/README.md b/metrics-server/vendor/github.com/emicklei/go-restful/README.md
new file mode 100644
index 0000000..f52c25a
--- /dev/null
+++ b/metrics-server/vendor/github.com/emicklei/go-restful/README.md
@@ -0,0 +1,88 @@
+go-restful
+==========
+package for building REST-style Web Services using Google Go
+
+[![Build Status](https://travis-ci.org/emicklei/go-restful.png)](https://travis-ci.org/emicklei/go-restful)
+[![Go Report Card](https://goreportcard.com/badge/github.com/emicklei/go-restful)](https://goreportcard.com/report/github.com/emicklei/go-restful)
+[![GoDoc](https://godoc.org/github.com/emicklei/go-restful?status.svg)](https://godoc.org/github.com/emicklei/go-restful)
+
+- [Code examples](https://github.com/emicklei/go-restful/tree/master/examples)
+
+REST asks developers to use HTTP methods explicitly and in a way that's consistent with the protocol definition. This basic REST design principle establishes a one-to-one mapping between create, read, update, and delete (CRUD) operations and HTTP methods. According to this mapping:
+
+- GET = Retrieve a representation of a resource
+- POST = Create if you are sending content to the server to create a subordinate of the specified resource collection, using some server-side algorithm.
+- PUT = Create if you are sending the full content of the specified resource (URI).
+- PUT = Update if you are updating the full content of the specified resource.
+- DELETE = Delete if you are requesting the server to delete the resource
+- PATCH = Update partial content of a resource
+- OPTIONS = Get information about the communication options for the request URI
+    
+### Example
+
+```Go
+ws := new(restful.WebService)
+ws.
+	Path("/users").
+	Consumes(restful.MIME_XML, restful.MIME_JSON).
+	Produces(restful.MIME_JSON, restful.MIME_XML)
+
+ws.Route(ws.GET("/{user-id}").To(u.findUser).
+	Doc("get a user").
+	Param(ws.PathParameter("user-id", "identifier of the user").DataType("string")).
+	Writes(User{}))		
+...
+	
+func (u UserResource) findUser(request *restful.Request, response *restful.Response) {
+	id := request.PathParameter("user-id")
+	...
+}
+```
+	
+[Full API of a UserResource](https://github.com/emicklei/go-restful/tree/master/examples/restful-user-resource.go) 
+		
+### Features
+
+- Routes for request → function mapping with path parameter (e.g. {id}) support
+- Configurable router:
+	- (default) Fast routing algorithm that allows static elements, regular expressions and dynamic parameters in the URL path (e.g. /meetings/{id} or /static/{subpath:*}
+	- Routing algorithm after [JSR311](http://jsr311.java.net/nonav/releases/1.1/spec/spec.html) that is implemented using (but does **not** accept) regular expressions
+- Request API for reading structs from JSON/XML and accesing parameters (path,query,header)
+- Response API for writing structs to JSON/XML and setting headers
+- Customizable encoding using EntityReaderWriter registration
+- Filters for intercepting the request → response flow on Service or Route level
+- Request-scoped variables using attributes
+- Containers for WebServices on different HTTP endpoints
+- Content encoding (gzip,deflate) of request and response payloads
+- Automatic responses on OPTIONS (using a filter)
+- Automatic CORS request handling (using a filter)
+- API declaration for Swagger UI ([go-restful-openapi](https://github.com/emicklei/go-restful-openapi), see [go-restful-swagger12](https://github.com/emicklei/go-restful-swagger12))
+- Panic recovery to produce HTTP 500, customizable using RecoverHandler(...)
+- Route errors produce HTTP 404/405/406/415 errors, customizable using ServiceErrorHandler(...)
+- Configurable (trace) logging
+- Customizable gzip/deflate readers and writers using CompressorProvider registration
+
+## How to customize
+There are several hooks to customize the behavior of the go-restful package.
+
+- Router algorithm
+- Panic recovery
+- JSON decoder
+- Trace logging
+- Compression
+- Encoders for other serializers
+- Use [jsoniter](https://github.com/json-iterator/go) by build this package using a tag, e.g. `go build -tags=jsoniter .`
+
+TODO: write examples of these.
+
+## Resources
+
+- [Example posted on blog](http://ernestmicklei.com/2012/11/go-restful-first-working-example/)
+- [Design explained on blog](http://ernestmicklei.com/2012/11/go-restful-api-design/)
+- [sourcegraph](https://sourcegraph.com/github.com/emicklei/go-restful)
+- [showcase: Zazkia - tcp proxy for testing resiliency](https://github.com/emicklei/zazkia)
+- [showcase: Mora - MongoDB REST Api server](https://github.com/emicklei/mora)
+
+Type ```git shortlog -s``` for a full list of contributors.
+
+© 2012 - 2018, http://ernestmicklei.com. MIT License. Contributions are welcome.
diff --git a/metrics-server/vendor/github.com/emicklei/go-restful/Srcfile b/metrics-server/vendor/github.com/emicklei/go-restful/Srcfile
new file mode 100644
index 0000000..16fd186
--- /dev/null
+++ b/metrics-server/vendor/github.com/emicklei/go-restful/Srcfile
@@ -0,0 +1 @@
+{"SkipDirs": ["examples"]}
diff --git a/metrics-server/vendor/github.com/emicklei/go-restful/bench_test.sh b/metrics-server/vendor/github.com/emicklei/go-restful/bench_test.sh
new file mode 100644
index 0000000..47ffbe4
--- /dev/null
+++ b/metrics-server/vendor/github.com/emicklei/go-restful/bench_test.sh
@@ -0,0 +1,10 @@
+#go test -run=none -file bench_test.go -test.bench . -cpuprofile=bench_test.out
+
+go test -c
+./go-restful.test -test.run=none -test.cpuprofile=tmp.prof -test.bench=BenchmarkMany
+./go-restful.test -test.run=none -test.cpuprofile=curly.prof -test.bench=BenchmarkManyCurly
+
+#go tool pprof go-restful.test tmp.prof
+go tool pprof go-restful.test curly.prof
+
+
diff --git a/metrics-server/vendor/github.com/emicklei/go-restful/compress.go b/metrics-server/vendor/github.com/emicklei/go-restful/compress.go
new file mode 100644
index 0000000..220b377
--- /dev/null
+++ b/metrics-server/vendor/github.com/emicklei/go-restful/compress.go
@@ -0,0 +1,123 @@
+package restful
+
+// Copyright 2013 Ernest Micklei. All rights reserved.
+// Use of this source code is governed by a license
+// that can be found in the LICENSE file.
+
+import (
+	"bufio"
+	"compress/gzip"
+	"compress/zlib"
+	"errors"
+	"io"
+	"net"
+	"net/http"
+	"strings"
+)
+
+// OBSOLETE : use restful.DefaultContainer.EnableContentEncoding(true) to change this setting.
+var EnableContentEncoding = false
+
+// CompressingResponseWriter is a http.ResponseWriter that can perform content encoding (gzip and zlib)
+type CompressingResponseWriter struct {
+	writer     http.ResponseWriter
+	compressor io.WriteCloser
+	encoding   string
+}
+
+// Header is part of http.ResponseWriter interface
+func (c *CompressingResponseWriter) Header() http.Header {
+	return c.writer.Header()
+}
+
+// WriteHeader is part of http.ResponseWriter interface
+func (c *CompressingResponseWriter) WriteHeader(status int) {
+	c.writer.WriteHeader(status)
+}
+
+// Write is part of http.ResponseWriter interface
+// It is passed through the compressor
+func (c *CompressingResponseWriter) Write(bytes []byte) (int, error) {
+	if c.isCompressorClosed() {
+		return -1, errors.New("Compressing error: tried to write data using closed compressor")
+	}
+	return c.compressor.Write(bytes)
+}
+
+// CloseNotify is part of http.CloseNotifier interface
+func (c *CompressingResponseWriter) CloseNotify() <-chan bool {
+	return c.writer.(http.CloseNotifier).CloseNotify()
+}
+
+// Close the underlying compressor
+func (c *CompressingResponseWriter) Close() error {
+	if c.isCompressorClosed() {
+		return errors.New("Compressing error: tried to close already closed compressor")
+	}
+
+	c.compressor.Close()
+	if ENCODING_GZIP == c.encoding {
+		currentCompressorProvider.ReleaseGzipWriter(c.compressor.(*gzip.Writer))
+	}
+	if ENCODING_DEFLATE == c.encoding {
+		currentCompressorProvider.ReleaseZlibWriter(c.compressor.(*zlib.Writer))
+	}
+	// gc hint needed?
+	c.compressor = nil
+	return nil
+}
+
+func (c *CompressingResponseWriter) isCompressorClosed() bool {
+	return nil == c.compressor
+}
+
+// Hijack implements the Hijacker interface
+// This is especially useful when combining Container.EnabledContentEncoding
+// in combination with websockets (for instance gorilla/websocket)
+func (c *CompressingResponseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) {
+	hijacker, ok := c.writer.(http.Hijacker)
+	if !ok {
+		return nil, nil, errors.New("ResponseWriter doesn't support Hijacker interface")
+	}
+	return hijacker.Hijack()
+}
+
+// WantsCompressedResponse reads the Accept-Encoding header to see if and which encoding is requested.
+func wantsCompressedResponse(httpRequest *http.Request) (bool, string) {
+	header := httpRequest.Header.Get(HEADER_AcceptEncoding)
+	gi := strings.Index(header, ENCODING_GZIP)
+	zi := strings.Index(header, ENCODING_DEFLATE)
+	// use in order of appearance
+	if gi == -1 {
+		return zi != -1, ENCODING_DEFLATE
+	} else if zi == -1 {
+		return gi != -1, ENCODING_GZIP
+	} else {
+		if gi < zi {
+			return true, ENCODING_GZIP
+		}
+		return true, ENCODING_DEFLATE
+	}
+}
+
+// NewCompressingResponseWriter create a CompressingResponseWriter for a known encoding = {gzip,deflate}
+func NewCompressingResponseWriter(httpWriter http.ResponseWriter, encoding string) (*CompressingResponseWriter, error) {
+	httpWriter.Header().Set(HEADER_ContentEncoding, encoding)
+	c := new(CompressingResponseWriter)
+	c.writer = httpWriter
+	var err error
+	if ENCODING_GZIP == encoding {
+		w := currentCompressorProvider.AcquireGzipWriter()
+		w.Reset(httpWriter)
+		c.compressor = w
+		c.encoding = ENCODING_GZIP
+	} else if ENCODING_DEFLATE == encoding {
+		w := currentCompressorProvider.AcquireZlibWriter()
+		w.Reset(httpWriter)
+		c.compressor = w
+		c.encoding = ENCODING_DEFLATE
+	} else {
+		return nil, errors.New("Unknown encoding:" + encoding)
+	}
+	return c, err
+}
diff --git a/metrics-server/vendor/github.com/emicklei/go-restful/compressor_cache.go b/metrics-server/vendor/github.com/emicklei/go-restful/compressor_cache.go
new file mode 100644
index 0000000..ee42601
--- /dev/null
+++ b/metrics-server/vendor/github.com/emicklei/go-restful/compressor_cache.go
@@ -0,0 +1,103 @@
+package restful
+
+// Copyright 2015 Ernest Micklei. All rights reserved.
+// Use of this source code is governed by a license
+// that can be found in the LICENSE file.
+
+import (
+	"compress/gzip"
+	"compress/zlib"
+)
+
+// BoundedCachedCompressors is a CompressorProvider that uses a cache with a fixed amount
+// of writers and readers (resources).
+// If a new resource is acquired and all are in use, it will return a new unmanaged resource.
+type BoundedCachedCompressors struct {
+	gzipWriters     chan *gzip.Writer
+	gzipReaders     chan *gzip.Reader
+	zlibWriters     chan *zlib.Writer
+	writersCapacity int
+	readersCapacity int
+}
+
+// NewBoundedCachedCompressors returns a new, with filled cache,  BoundedCachedCompressors.
+func NewBoundedCachedCompressors(writersCapacity, readersCapacity int) *BoundedCachedCompressors {
+	b := &BoundedCachedCompressors{
+		gzipWriters:     make(chan *gzip.Writer, writersCapacity),
+		gzipReaders:     make(chan *gzip.Reader, readersCapacity),
+		zlibWriters:     make(chan *zlib.Writer, writersCapacity),
+		writersCapacity: writersCapacity,
+		readersCapacity: readersCapacity,
+	}
+	for ix := 0; ix < writersCapacity; ix++ {
+		b.gzipWriters <- newGzipWriter()
+		b.zlibWriters <- newZlibWriter()
+	}
+	for ix := 0; ix < readersCapacity; ix++ {
+		b.gzipReaders <- newGzipReader()
+	}
+	return b
+}
+
+// AcquireGzipWriter returns an resettable *gzip.Writer. Needs to be released.
+func (b *BoundedCachedCompressors) AcquireGzipWriter() *gzip.Writer {
+	var writer *gzip.Writer
+	select {
+	case writer, _ = <-b.gzipWriters:
+	default:
+		// return a new unmanaged one
+		writer = newGzipWriter()
+	}
+	return writer
+}
+
+// ReleaseGzipWriter accepts a writer (does not have to be one that was cached)
+// only when the cache has room for it. It will ignore it otherwise.
+func (b *BoundedCachedCompressors) ReleaseGzipWriter(w *gzip.Writer) {
+	// forget the unmanaged ones
+	if len(b.gzipWriters) < b.writersCapacity {
+		b.gzipWriters <- w
+	}
+}
+
+// AcquireGzipReader returns a *gzip.Reader. Needs to be released.
+func (b *BoundedCachedCompressors) AcquireGzipReader() *gzip.Reader {
+	var reader *gzip.Reader
+	select {
+	case reader, _ = <-b.gzipReaders:
+	default:
+		// return a new unmanaged one
+		reader = newGzipReader()
+	}
+	return reader
+}
+
+// ReleaseGzipReader accepts a reader (does not have to be one that was cached)
+// only when the cache has room for it. It will ignore it otherwise.
+func (b *BoundedCachedCompressors) ReleaseGzipReader(r *gzip.Reader) {
+	// forget the unmanaged ones
+	if len(b.gzipReaders) < b.readersCapacity {
+		b.gzipReaders <- r
+	}
+}
+
+// AcquireZlibWriter returns an resettable *zlib.Writer. Needs to be released.
+func (b *BoundedCachedCompressors) AcquireZlibWriter() *zlib.Writer {
+	var writer *zlib.Writer
+	select {
+	case writer, _ = <-b.zlibWriters:
+	default:
+		// return a new unmanaged one
+		writer = newZlibWriter()
+	}
+	return writer
+}
+
+// ReleaseZlibWriter accepts a writer (does not have to be one that was cached)
+// only when the cache has room for it. It will ignore it otherwise.
+func (b *BoundedCachedCompressors) ReleaseZlibWriter(w *zlib.Writer) {
+	// forget the unmanaged ones
+	if len(b.zlibWriters) < b.writersCapacity {
+		b.zlibWriters <- w
+	}
+}
diff --git a/metrics-server/vendor/github.com/emicklei/go-restful/compressor_pools.go b/metrics-server/vendor/github.com/emicklei/go-restful/compressor_pools.go
new file mode 100644
index 0000000..d866ce6
--- /dev/null
+++ b/metrics-server/vendor/github.com/emicklei/go-restful/compressor_pools.go
@@ -0,0 +1,91 @@
+package restful
+
+// Copyright 2015 Ernest Micklei. All rights reserved.
+// Use of this source code is governed by a license
+// that can be found in the LICENSE file.
+
+import (
+	"bytes"
+	"compress/gzip"
+	"compress/zlib"
+	"sync"
+)
+
+// SyncPoolCompessors is a CompressorProvider that use the standard sync.Pool.
+type SyncPoolCompessors struct {
+	GzipWriterPool *sync.Pool
+	GzipReaderPool *sync.Pool
+	ZlibWriterPool *sync.Pool
+}
+
+// NewSyncPoolCompessors returns a new ("empty") SyncPoolCompessors.
+func NewSyncPoolCompessors() *SyncPoolCompessors {
+	return &SyncPoolCompessors{
+		GzipWriterPool: &sync.Pool{
+			New: func() interface{} { return newGzipWriter() },
+		},
+		GzipReaderPool: &sync.Pool{
+			New: func() interface{} { return newGzipReader() },
+		},
+		ZlibWriterPool: &sync.Pool{
+			New: func() interface{} { return newZlibWriter() },
+		},
+	}
+}
+
+func (s *SyncPoolCompessors) AcquireGzipWriter() *gzip.Writer {
+	return s.GzipWriterPool.Get().(*gzip.Writer)
+}
+
+func (s *SyncPoolCompessors) ReleaseGzipWriter(w *gzip.Writer) {
+	s.GzipWriterPool.Put(w)
+}
+
+func (s *SyncPoolCompessors) AcquireGzipReader() *gzip.Reader {
+	return s.GzipReaderPool.Get().(*gzip.Reader)
+}
+
+func (s *SyncPoolCompessors) ReleaseGzipReader(r *gzip.Reader) {
+	s.GzipReaderPool.Put(r)
+}
+
+func (s *SyncPoolCompessors) AcquireZlibWriter() *zlib.Writer {
+	return s.ZlibWriterPool.Get().(*zlib.Writer)
+}
+
+func (s *SyncPoolCompessors) ReleaseZlibWriter(w *zlib.Writer) {
+	s.ZlibWriterPool.Put(w)
+}
+
+func newGzipWriter() *gzip.Writer {
+	// create with an empty bytes writer; it will be replaced before using the gzipWriter
+	writer, err := gzip.NewWriterLevel(new(bytes.Buffer), gzip.BestSpeed)
+	if err != nil {
+		panic(err.Error())
+	}
+	return writer
+}
+
+func newGzipReader() *gzip.Reader {
+	// create with an empty reader (but with GZIP header); it will be replaced before using the gzipReader
+	// we can safely use currentCompressProvider because it is set on package initialization.
+	w := currentCompressorProvider.AcquireGzipWriter()
+	defer currentCompressorProvider.ReleaseGzipWriter(w)
+	b := new(bytes.Buffer)
+	w.Reset(b)
+	w.Flush()
+	w.Close()
+	reader, err := gzip.NewReader(bytes.NewReader(b.Bytes()))
+	if err != nil {
+		panic(err.Error())
+	}
+	return reader
+}
+
+func newZlibWriter() *zlib.Writer {
+	writer, err := zlib.NewWriterLevel(new(bytes.Buffer), gzip.BestSpeed)
+	if err != nil {
+		panic(err.Error())
+	}
+	return writer
+}
diff --git a/metrics-server/vendor/github.com/emicklei/go-restful/compressors.go b/metrics-server/vendor/github.com/emicklei/go-restful/compressors.go
new file mode 100644
index 0000000..9db4a8c
--- /dev/null
+++ b/metrics-server/vendor/github.com/emicklei/go-restful/compressors.go
@@ -0,0 +1,54 @@
+package restful
+
+// Copyright 2015 Ernest Micklei. All rights reserved.
+// Use of this source code is governed by a license
+// that can be found in the LICENSE file.
+
+import (
+	"compress/gzip"
+	"compress/zlib"
+)
+
+// CompressorProvider describes a component that can provider compressors for the std methods.
+type CompressorProvider interface {
+	// Returns a *gzip.Writer which needs to be released later.
+	// Before using it, call Reset().
+	AcquireGzipWriter() *gzip.Writer
+
+	// Releases an acquired *gzip.Writer.
+	ReleaseGzipWriter(w *gzip.Writer)
+
+	// Returns a *gzip.Reader which needs to be released later.
+	AcquireGzipReader() *gzip.Reader
+
+	// Releases an acquired *gzip.Reader.
+	ReleaseGzipReader(w *gzip.Reader)
+
+	// Returns a *zlib.Writer which needs to be released later.
+	// Before using it, call Reset().
+	AcquireZlibWriter() *zlib.Writer
+
+	// Releases an acquired *zlib.Writer.
+	ReleaseZlibWriter(w *zlib.Writer)
+}
+
+// DefaultCompressorProvider is the actual provider of compressors (zlib or gzip).
+var currentCompressorProvider CompressorProvider
+
+func init() {
+	currentCompressorProvider = NewSyncPoolCompessors()
+}
+
+// CurrentCompressorProvider returns the current CompressorProvider.
+// It is initialized using a SyncPoolCompessors.
+func CurrentCompressorProvider() CompressorProvider {
+	return currentCompressorProvider
+}
+
+// SetCompressorProvider sets the actual provider of compressors (zlib or gzip).
+func SetCompressorProvider(p CompressorProvider) {
+	if p == nil {
+		panic("cannot set compressor provider to nil")
+	}
+	currentCompressorProvider = p
+}
diff --git a/metrics-server/vendor/github.com/emicklei/go-restful/constants.go b/metrics-server/vendor/github.com/emicklei/go-restful/constants.go
new file mode 100644
index 0000000..203439c
--- /dev/null
+++ b/metrics-server/vendor/github.com/emicklei/go-restful/constants.go
@@ -0,0 +1,30 @@
+package restful
+
+// Copyright 2013 Ernest Micklei. All rights reserved.
+// Use of this source code is governed by a license
+// that can be found in the LICENSE file.
+
+const (
+	MIME_XML   = "application/xml"          // Accept or Content-Type used in Consumes() and/or Produces()
+	MIME_JSON  = "application/json"         // Accept or Content-Type used in Consumes() and/or Produces()
+	MIME_OCTET = "application/octet-stream" // If Content-Type is not present in request, use the default
+
+	HEADER_Allow                         = "Allow"
+	HEADER_Accept                        = "Accept"
+	HEADER_Origin                        = "Origin"
+	HEADER_ContentType                   = "Content-Type"
+	HEADER_LastModified                  = "Last-Modified"
+	HEADER_AcceptEncoding                = "Accept-Encoding"
+	HEADER_ContentEncoding               = "Content-Encoding"
+	HEADER_AccessControlExposeHeaders    = "Access-Control-Expose-Headers"
+	HEADER_AccessControlRequestMethod    = "Access-Control-Request-Method"
+	HEADER_AccessControlRequestHeaders   = "Access-Control-Request-Headers"
+	HEADER_AccessControlAllowMethods     = "Access-Control-Allow-Methods"
+	HEADER_AccessControlAllowOrigin      = "Access-Control-Allow-Origin"
+	HEADER_AccessControlAllowCredentials = "Access-Control-Allow-Credentials"
+	HEADER_AccessControlAllowHeaders     = "Access-Control-Allow-Headers"
+	HEADER_AccessControlMaxAge           = "Access-Control-Max-Age"
+
+	ENCODING_GZIP    = "gzip"
+	ENCODING_DEFLATE = "deflate"
+)
diff --git a/metrics-server/vendor/github.com/emicklei/go-restful/container.go b/metrics-server/vendor/github.com/emicklei/go-restful/container.go
new file mode 100644
index 0000000..b4ad153
--- /dev/null
+++ b/metrics-server/vendor/github.com/emicklei/go-restful/container.go
@@ -0,0 +1,371 @@
+package restful
+
+// Copyright 2013 Ernest Micklei. All rights reserved.
+// Use of this source code is governed by a license
+// that can be found in the LICENSE file.
+
+import (
+	"bytes"
+	"errors"
+	"fmt"
+	"net/http"
+	"os"
+	"runtime"
+	"strings"
+	"sync"
+
+	"github.com/emicklei/go-restful/log"
+)
+
+// Container holds a collection of WebServices and a http.ServeMux to dispatch http requests.
+// The requests are further dispatched to routes of WebServices using a RouteSelector
+type Container struct {
+	webServicesLock        sync.RWMutex
+	webServices            []*WebService
+	ServeMux               *http.ServeMux
+	isRegisteredOnRoot     bool
+	containerFilters       []FilterFunction
+	doNotRecover           bool // default is true
+	recoverHandleFunc      RecoverHandleFunction
+	serviceErrorHandleFunc ServiceErrorHandleFunction
+	router                 RouteSelector // default is a CurlyRouter (RouterJSR311 is a slower alternative)
+	contentEncodingEnabled bool          // default is false
+}
+
+// NewContainer creates a new Container using a new ServeMux and default router (CurlyRouter)
+func NewContainer() *Container {
+	return &Container{
+		webServices:            []*WebService{},
+		ServeMux:               http.NewServeMux(),
+		isRegisteredOnRoot:     false,
+		containerFilters:       []FilterFunction{},
+		doNotRecover:           true,
+		recoverHandleFunc:      logStackOnRecover,
+		serviceErrorHandleFunc: writeServiceError,
+		router:                 CurlyRouter{},
+		contentEncodingEnabled: false}
+}
+
+// RecoverHandleFunction declares functions that can be used to handle a panic situation.
+// The first argument is what recover() returns. The second must be used to communicate an error response.
+type RecoverHandleFunction func(interface{}, http.ResponseWriter)
+
+// RecoverHandler changes the default function (logStackOnRecover) to be called
+// when a panic is detected. DoNotRecover must be have its default value (=false).
+func (c *Container) RecoverHandler(handler RecoverHandleFunction) {
+	c.recoverHandleFunc = handler
+}
+
+// ServiceErrorHandleFunction declares functions that can be used to handle a service error situation.
+// The first argument is the service error, the second is the request that resulted in the error and
+// the third must be used to communicate an error response.
+type ServiceErrorHandleFunction func(ServiceError, *Request, *Response)
+
+// ServiceErrorHandler changes the default function (writeServiceError) to be called
+// when a ServiceError is detected.
+func (c *Container) ServiceErrorHandler(handler ServiceErrorHandleFunction) {
+	c.serviceErrorHandleFunc = handler
+}
+
+// DoNotRecover controls whether panics will be caught to return HTTP 500.
+// If set to true, Route functions are responsible for handling any error situation.
+// Default value is true.
+func (c *Container) DoNotRecover(doNot bool) {
+	c.doNotRecover = doNot
+}
+
+// Router changes the default Router (currently CurlyRouter)
+func (c *Container) Router(aRouter RouteSelector) {
+	c.router = aRouter
+}
+
+// EnableContentEncoding (default=false) allows for GZIP or DEFLATE encoding of responses.
+func (c *Container) EnableContentEncoding(enabled bool) {
+	c.contentEncodingEnabled = enabled
+}
+
+// Add a WebService to the Container. It will detect duplicate root paths and exit in that case.
+func (c *Container) Add(service *WebService) *Container {
+	c.webServicesLock.Lock()
+	defer c.webServicesLock.Unlock()
+
+	// if rootPath was not set then lazy initialize it
+	if len(service.rootPath) == 0 {
+		service.Path("/")
+	}
+
+	// cannot have duplicate root paths
+	for _, each := range c.webServices {
+		if each.RootPath() == service.RootPath() {
+			log.Printf("[restful] WebService with duplicate root path detected:['%v']", each)
+			os.Exit(1)
+		}
+	}
+
+	// If not registered on root then add specific mapping
+	if !c.isRegisteredOnRoot {
+		c.isRegisteredOnRoot = c.addHandler(service, c.ServeMux)
+	}
+	c.webServices = append(c.webServices, service)
+	return c
+}
+
+// addHandler may set a new HandleFunc for the serveMux
+// this function must run inside the critical region protected by the webServicesLock.
+// returns true if the function was registered on root ("/")
+func (c *Container) addHandler(service *WebService, serveMux *http.ServeMux) bool {
+	pattern := fixedPrefixPath(service.RootPath())
+	// check if root path registration is needed
+	if "/" == pattern || "" == pattern {
+		serveMux.HandleFunc("/", c.dispatch)
+		return true
+	}
+	// detect if registration already exists
+	alreadyMapped := false
+	for _, each := range c.webServices {
+		if each.RootPath() == service.RootPath() {
+			alreadyMapped = true
+			break
+		}
+	}
+	if !alreadyMapped {
+		serveMux.HandleFunc(pattern, c.dispatch)
+		if !strings.HasSuffix(pattern, "/") {
+			serveMux.HandleFunc(pattern+"/", c.dispatch)
+		}
+	}
+	return false
+}
+
+func (c *Container) Remove(ws *WebService) error {
+	if c.ServeMux == http.DefaultServeMux {
+		errMsg := fmt.Sprintf("[restful] cannot remove a WebService from a Container using the DefaultServeMux: ['%v']", ws)
+		log.Print(errMsg)
+		return errors.New(errMsg)
+	}
+	c.webServicesLock.Lock()
+	defer c.webServicesLock.Unlock()
+	// build a new ServeMux and re-register all WebServices
+	newServeMux := http.NewServeMux()
+	newServices := []*WebService{}
+	newIsRegisteredOnRoot := false
+	for _, each := range c.webServices {
+		if each.rootPath != ws.rootPath {
+			// If not registered on root then add specific mapping
+			if !newIsRegisteredOnRoot {
+				newIsRegisteredOnRoot = c.addHandler(each, newServeMux)
+			}
+			newServices = append(newServices, each)
+		}
+	}
+	c.webServices, c.ServeMux, c.isRegisteredOnRoot = newServices, newServeMux, newIsRegisteredOnRoot
+	return nil
+}
+
+// logStackOnRecover is the default RecoverHandleFunction and is called
+// when DoNotRecover is false and the recoverHandleFunc is not set for the container.
+// Default implementation logs the stacktrace and writes the stacktrace on the response.
+// This may be a security issue as it exposes sourcecode information.
+func logStackOnRecover(panicReason interface{}, httpWriter http.ResponseWriter) {
+	var buffer bytes.Buffer
+	buffer.WriteString(fmt.Sprintf("[restful] recover from panic situation: - %v\r\n", panicReason))
+	for i := 2; ; i += 1 {
+		_, file, line, ok := runtime.Caller(i)
+		if !ok {
+			break
+		}
+		buffer.WriteString(fmt.Sprintf("    %s:%d\r\n", file, line))
+	}
+	log.Print(buffer.String())
+	httpWriter.WriteHeader(http.StatusInternalServerError)
+	httpWriter.Write(buffer.Bytes())
+}
+
+// writeServiceError is the default ServiceErrorHandleFunction and is called
+// when a ServiceError is returned during route selection. Default implementation
+// calls resp.WriteErrorString(err.Code, err.Message)
+func writeServiceError(err ServiceError, req *Request, resp *Response) {
+	resp.WriteErrorString(err.Code, err.Message)
+}
+
+// Dispatch the incoming Http Request to a matching WebService.
+func (c *Container) Dispatch(httpWriter http.ResponseWriter, httpRequest *http.Request) {
+	if httpWriter == nil {
+		panic("httpWriter cannot be nil")
+	}
+	if httpRequest == nil {
+		panic("httpRequest cannot be nil")
+	}
+	c.dispatch(httpWriter, httpRequest)
+}
+
+// Dispatch the incoming Http Request to a matching WebService.
+func (c *Container) dispatch(httpWriter http.ResponseWriter, httpRequest *http.Request) {
+	writer := httpWriter
+
+	// CompressingResponseWriter should be closed after all operations are done
+	defer func() {
+		if compressWriter, ok := writer.(*CompressingResponseWriter); ok {
+			compressWriter.Close()
+		}
+	}()
+
+	// Instal panic recovery unless told otherwise
+	if !c.doNotRecover { // catch all for 500 response
+		defer func() {
+			if r := recover(); r != nil {
+				c.recoverHandleFunc(r, writer)
+				return
+			}
+		}()
+	}
+
+	// Detect if compression is needed
+	// assume without compression, test for override
+	if c.contentEncodingEnabled {
+		doCompress, encoding := wantsCompressedResponse(httpRequest)
+		if doCompress {
+			var err error
+			writer, err = NewCompressingResponseWriter(httpWriter, encoding)
+			if err != nil {
+				log.Print("[restful] unable to install compressor: ", err)
+				httpWriter.WriteHeader(http.StatusInternalServerError)
+				return
+			}
+		}
+	}
+	// Find best match Route ; err is non nil if no match was found
+	var webService *WebService
+	var route *Route
+	var err error
+	func() {
+		c.webServicesLock.RLock()
+		defer c.webServicesLock.RUnlock()
+		webService, route, err = c.router.SelectRoute(
+			c.webServices,
+			httpRequest)
+	}()
+	if err != nil {
+		// a non-200 response has already been written
+		// run container filters anyway ; they should not touch the response...
+		chain := FilterChain{Filters: c.containerFilters, Target: func(req *Request, resp *Response) {
+			switch err.(type) {
+			case ServiceError:
+				ser := err.(ServiceError)
+				c.serviceErrorHandleFunc(ser, req, resp)
+			}
+			// TODO
+		}}
+		chain.ProcessFilter(NewRequest(httpRequest), NewResponse(writer))
+		return
+	}
+	pathProcessor, routerProcessesPath := c.router.(PathProcessor)
+	if !routerProcessesPath {
+		pathProcessor = defaultPathProcessor{}
+	}
+	pathParams := pathProcessor.ExtractParameters(route, webService, httpRequest.URL.Path)
+	wrappedRequest, wrappedResponse := route.wrapRequestResponse(writer, httpRequest, pathParams)
+	// pass through filters (if any)
+	if len(c.containerFilters)+len(webService.filters)+len(route.Filters) > 0 {
+		// compose filter chain
+		allFilters := []FilterFunction{}
+		allFilters = append(allFilters, c.containerFilters...)
+		allFilters = append(allFilters, webService.filters...)
+		allFilters = append(allFilters, route.Filters...)
+		chain := FilterChain{Filters: allFilters, Target: func(req *Request, resp *Response) {
+			// handle request by route after passing all filters
+			route.Function(wrappedRequest, wrappedResponse)
+		}}
+		chain.ProcessFilter(wrappedRequest, wrappedResponse)
+	} else {
+		// no filters, handle request by route
+		route.Function(wrappedRequest, wrappedResponse)
+	}
+}
+
+// fixedPrefixPath returns the fixed part of the partspec ; it may include template vars {}
+func fixedPrefixPath(pathspec string) string {
+	varBegin := strings.Index(pathspec, "{")
+	if -1 == varBegin {
+		return pathspec
+	}
+	return pathspec[:varBegin]
+}
+
+// ServeHTTP implements net/http.Handler therefore a Container can be a Handler in a http.Server
+func (c *Container) ServeHTTP(httpwriter http.ResponseWriter, httpRequest *http.Request) {
+	c.ServeMux.ServeHTTP(httpwriter, httpRequest)
+}
+
+// Handle registers the handler for the given pattern. If a handler already exists for pattern, Handle panics.
+func (c *Container) Handle(pattern string, handler http.Handler) {
+	c.ServeMux.Handle(pattern, handler)
+}
+
+// HandleWithFilter registers the handler for the given pattern.
+// Container's filter chain is applied for handler.
+// If a handler already exists for pattern, HandleWithFilter panics.
+func (c *Container) HandleWithFilter(pattern string, handler http.Handler) {
+	f := func(httpResponse http.ResponseWriter, httpRequest *http.Request) {
+		if len(c.containerFilters) == 0 {
+			handler.ServeHTTP(httpResponse, httpRequest)
+			return
+		}
+
+		chain := FilterChain{Filters: c.containerFilters, Target: func(req *Request, resp *Response) {
+			handler.ServeHTTP(httpResponse, httpRequest)
+		}}
+		chain.ProcessFilter(NewRequest(httpRequest), NewResponse(httpResponse))
+	}
+
+	c.Handle(pattern, http.HandlerFunc(f))
+}
+
+// Filter appends a container FilterFunction. These are called before dispatching
+// a http.Request to a WebService from the container
+func (c *Container) Filter(filter FilterFunction) {
+	c.containerFilters = append(c.containerFilters, filter)
+}
+
+// RegisteredWebServices returns the collections of added WebServices
+func (c *Container) RegisteredWebServices() []*WebService {
+	c.webServicesLock.RLock()
+	defer c.webServicesLock.RUnlock()
+	result := make([]*WebService, len(c.webServices))
+	for ix := range c.webServices {
+		result[ix] = c.webServices[ix]
+	}
+	return result
+}
+
+// computeAllowedMethods returns a list of HTTP methods that are valid for a Request
+func (c *Container) computeAllowedMethods(req *Request) []string {
+	// Go through all RegisteredWebServices() and all its Routes to collect the options
+	methods := []string{}
+	requestPath := req.Request.URL.Path
+	for _, ws := range c.RegisteredWebServices() {
+		matches := ws.pathExpr.Matcher.FindStringSubmatch(requestPath)
+		if matches != nil {
+			finalMatch := matches[len(matches)-1]
+			for _, rt := range ws.Routes() {
+				matches := rt.pathExpr.Matcher.FindStringSubmatch(finalMatch)
+				if matches != nil {
+					lastMatch := matches[len(matches)-1]
+					if lastMatch == "" || lastMatch == "/" { // do not include if value is neither empty nor ‘/’.
+						methods = append(methods, rt.Method)
+					}
+				}
+			}
+		}
+	}
+	// methods = append(methods, "OPTIONS")  not sure about this
+	return methods
+}
+
+// newBasicRequestResponse creates a pair of Request,Response from its http versions.
+// It is basic because no parameter or (produces) content-type information is given.
+func newBasicRequestResponse(httpWriter http.ResponseWriter, httpRequest *http.Request) (*Request, *Response) {
+	resp := NewResponse(httpWriter)
+	resp.requestAccept = httpRequest.Header.Get(HEADER_Accept)
+	return NewRequest(httpRequest), resp
+}
diff --git a/metrics-server/vendor/github.com/emicklei/go-restful/cors_filter.go b/metrics-server/vendor/github.com/emicklei/go-restful/cors_filter.go
new file mode 100644
index 0000000..1efeef0
--- /dev/null
+++ b/metrics-server/vendor/github.com/emicklei/go-restful/cors_filter.go
@@ -0,0 +1,202 @@
+package restful
+
+// Copyright 2013 Ernest Micklei. All rights reserved.
+// Use of this source code is governed by a license
+// that can be found in the LICENSE file.
+
+import (
+	"regexp"
+	"strconv"
+	"strings"
+)
+
+// CrossOriginResourceSharing is used to create a Container Filter that implements CORS.
+// Cross-origin resource sharing (CORS) is a mechanism that allows JavaScript on a web page
+// to make XMLHttpRequests to another domain, not the domain the JavaScript originated from.
+//
+// http://en.wikipedia.org/wiki/Cross-origin_resource_sharing
+// http://enable-cors.org/server.html
+// http://www.html5rocks.com/en/tutorials/cors/#toc-handling-a-not-so-simple-request
+type CrossOriginResourceSharing struct {
+	ExposeHeaders  []string // list of Header names
+	AllowedHeaders []string // list of Header names
+	AllowedDomains []string // list of allowed values for Http Origin. An allowed value can be a regular expression to support subdomain matching. If empty all are allowed.
+	AllowedMethods []string
+	MaxAge         int // number of seconds before requiring new Options request
+	CookiesAllowed bool
+	Container      *Container
+
+	allowedOriginPatterns []*regexp.Regexp // internal field for origin regexp check.
+}
+
+// Filter is a filter function that implements the CORS flow as documented on http://enable-cors.org/server.html
+// and http://www.html5rocks.com/static/images/cors_server_flowchart.png
+func (c CrossOriginResourceSharing) Filter(req *Request, resp *Response, chain *FilterChain) {
+	origin := req.Request.Header.Get(HEADER_Origin)
+	if len(origin) == 0 {
+		if trace {
+			traceLogger.Print("no Http header Origin set")
+		}
+		chain.ProcessFilter(req, resp)
+		return
+	}
+	if !c.isOriginAllowed(origin) { // check whether this origin is allowed
+		if trace {
+			traceLogger.Printf("HTTP Origin:%s is not part of %v, neither matches any part of %v", origin, c.AllowedDomains, c.allowedOriginPatterns)
+		}
+		chain.ProcessFilter(req, resp)
+		return
+	}
+	if req.Request.Method != "OPTIONS" {
+		c.doActualRequest(req, resp)
+		chain.ProcessFilter(req, resp)
+		return
+	}
+	if acrm := req.Request.Header.Get(HEADER_AccessControlRequestMethod); acrm != "" {
+		c.doPreflightRequest(req, resp)
+	} else {
+		c.doActualRequest(req, resp)
+		chain.ProcessFilter(req, resp)
+		return
+	}
+}
+
+func (c CrossOriginResourceSharing) doActualRequest(req *Request, resp *Response) {
+	c.setOptionsHeaders(req, resp)
+	// continue processing the response
+}
+
+func (c *CrossOriginResourceSharing) doPreflightRequest(req *Request, resp *Response) {
+	if len(c.AllowedMethods) == 0 {
+		if c.Container == nil {
+			c.AllowedMethods = DefaultContainer.computeAllowedMethods(req)
+		} else {
+			c.AllowedMethods = c.Container.computeAllowedMethods(req)
+		}
+	}
+
+	acrm := req.Request.Header.Get(HEADER_AccessControlRequestMethod)
+	if !c.isValidAccessControlRequestMethod(acrm, c.AllowedMethods) {
+		if trace {
+			traceLogger.Printf("Http header %s:%s is not in %v",
+				HEADER_AccessControlRequestMethod,
+				acrm,
+				c.AllowedMethods)
+		}
+		return
+	}
+	acrhs := req.Request.Header.Get(HEADER_AccessControlRequestHeaders)
+	if len(acrhs) > 0 {
+		for _, each := range strings.Split(acrhs, ",") {
+			if !c.isValidAccessControlRequestHeader(strings.Trim(each, " ")) {
+				if trace {
+					traceLogger.Printf("Http header %s:%s is not in %v",
+						HEADER_AccessControlRequestHeaders,
+						acrhs,
+						c.AllowedHeaders)
+				}
+				return
+			}
+		}
+	}
+	resp.AddHeader(HEADER_AccessControlAllowMethods, strings.Join(c.AllowedMethods, ","))
+	resp.AddHeader(HEADER_AccessControlAllowHeaders, acrhs)
+	c.setOptionsHeaders(req, resp)
+
+	// return http 200 response, no body
+}
+
+func (c CrossOriginResourceSharing) setOptionsHeaders(req *Request, resp *Response) {
+	c.checkAndSetExposeHeaders(resp)
+	c.setAllowOriginHeader(req, resp)
+	c.checkAndSetAllowCredentials(resp)
+	if c.MaxAge > 0 {
+		resp.AddHeader(HEADER_AccessControlMaxAge, strconv.Itoa(c.MaxAge))
+	}
+}
+
+func (c CrossOriginResourceSharing) isOriginAllowed(origin string) bool {
+	if len(origin) == 0 {
+		return false
+	}
+	if len(c.AllowedDomains) == 0 {
+		return true
+	}
+
+	allowed := false
+	for _, domain := range c.AllowedDomains {
+		if domain == origin {
+			allowed = true
+			break
+		}
+	}
+
+	if !allowed {
+		if len(c.allowedOriginPatterns) == 0 {
+			// compile allowed domains to allowed origin patterns
+			allowedOriginRegexps, err := compileRegexps(c.AllowedDomains)
+			if err != nil {
+				return false
+			}
+			c.allowedOriginPatterns = allowedOriginRegexps
+		}
+
+		for _, pattern := range c.allowedOriginPatterns {
+			if allowed = pattern.MatchString(origin); allowed {
+				break
+			}
+		}
+	}
+
+	return allowed
+}
+
+func (c CrossOriginResourceSharing) setAllowOriginHeader(req *Request, resp *Response) {
+	origin := req.Request.Header.Get(HEADER_Origin)
+	if c.isOriginAllowed(origin) {
+		resp.AddHeader(HEADER_AccessControlAllowOrigin, origin)
+	}
+}
+
+func (c CrossOriginResourceSharing) checkAndSetExposeHeaders(resp *Response) {
+	if len(c.ExposeHeaders) > 0 {
+		resp.AddHeader(HEADER_AccessControlExposeHeaders, strings.Join(c.ExposeHeaders, ","))
+	}
+}
+
+func (c CrossOriginResourceSharing) checkAndSetAllowCredentials(resp *Response) {
+	if c.CookiesAllowed {
+		resp.AddHeader(HEADER_AccessControlAllowCredentials, "true")
+	}
+}
+
+func (c CrossOriginResourceSharing) isValidAccessControlRequestMethod(method string, allowedMethods []string) bool {
+	for _, each := range allowedMethods {
+		if each == method {
+			return true
+		}
+	}
+	return false
+}
+
+func (c CrossOriginResourceSharing) isValidAccessControlRequestHeader(header string) bool {
+	for _, each := range c.AllowedHeaders {
+		if strings.ToLower(each) == strings.ToLower(header) {
+			return true
+		}
+	}
+	return false
+}
+
+// Take a list of strings and compile 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 regexps, err
+		}
+		regexps = append(regexps, r)
+	}
+	return regexps, nil
+}
diff --git a/metrics-server/vendor/github.com/emicklei/go-restful/coverage.sh b/metrics-server/vendor/github.com/emicklei/go-restful/coverage.sh
new file mode 100644
index 0000000..e27dbf1
--- /dev/null
+++ b/metrics-server/vendor/github.com/emicklei/go-restful/coverage.sh
@@ -0,0 +1,2 @@
+go test -coverprofile=coverage.out
+go tool cover -html=coverage.out
\ No newline at end of file
diff --git a/metrics-server/vendor/github.com/emicklei/go-restful/curly.go b/metrics-server/vendor/github.com/emicklei/go-restful/curly.go
new file mode 100644
index 0000000..79f1f5a
--- /dev/null
+++ b/metrics-server/vendor/github.com/emicklei/go-restful/curly.go
@@ -0,0 +1,164 @@
+package restful
+
+// Copyright 2013 Ernest Micklei. All rights reserved.
+// Use of this source code is governed by a license
+// that can be found in the LICENSE file.
+
+import (
+	"net/http"
+	"regexp"
+	"sort"
+	"strings"
+)
+
+// CurlyRouter expects Routes with paths that contain zero or more parameters in curly brackets.
+type CurlyRouter struct{}
+
+// SelectRoute is part of the Router interface and returns the best match
+// for the WebService and its Route for the given Request.
+func (c CurlyRouter) SelectRoute(
+	webServices []*WebService,
+	httpRequest *http.Request) (selectedService *WebService, selected *Route, err error) {
+
+	requestTokens := tokenizePath(httpRequest.URL.Path)
+
+	detectedService := c.detectWebService(requestTokens, webServices)
+	if detectedService == nil {
+		if trace {
+			traceLogger.Printf("no WebService was found to match URL path:%s\n", httpRequest.URL.Path)
+		}
+		return nil, nil, NewError(http.StatusNotFound, "404: Page Not Found")
+	}
+	candidateRoutes := c.selectRoutes(detectedService, requestTokens)
+	if len(candidateRoutes) == 0 {
+		if trace {
+			traceLogger.Printf("no Route in WebService with path %s was found to match URL path:%s\n", detectedService.rootPath, httpRequest.URL.Path)
+		}
+		return detectedService, nil, NewError(http.StatusNotFound, "404: Page Not Found")
+	}
+	selectedRoute, err := c.detectRoute(candidateRoutes, httpRequest)
+	if selectedRoute == nil {
+		return detectedService, nil, err
+	}
+	return detectedService, selectedRoute, nil
+}
+
+// selectRoutes return a collection of Route from a WebService that matches the path tokens from the request.
+func (c CurlyRouter) selectRoutes(ws *WebService, requestTokens []string) sortableCurlyRoutes {
+	candidates := sortableCurlyRoutes{}
+	for _, each := range ws.routes {
+		matches, paramCount, staticCount := c.matchesRouteByPathTokens(each.pathParts, requestTokens)
+		if matches {
+			candidates.add(curlyRoute{each, paramCount, staticCount}) // TODO make sure Routes() return pointers?
+		}
+	}
+	sort.Sort(sort.Reverse(candidates))
+	return candidates
+}
+
+// matchesRouteByPathTokens computes whether it matches, howmany parameters do match and what the number of static path elements are.
+func (c CurlyRouter) matchesRouteByPathTokens(routeTokens, requestTokens []string) (matches bool, paramCount int, staticCount int) {
+	if len(routeTokens) < len(requestTokens) {
+		// proceed in matching only if last routeToken is wildcard
+		count := len(routeTokens)
+		if count == 0 || !strings.HasSuffix(routeTokens[count-1], "*}") {
+			return false, 0, 0
+		}
+		// proceed
+	}
+	for i, routeToken := range routeTokens {
+		if i == len(requestTokens) {
+			// reached end of request path
+			return false, 0, 0
+		}
+		requestToken := requestTokens[i]
+		if strings.HasPrefix(routeToken, "{") {
+			paramCount++
+			if colon := strings.Index(routeToken, ":"); colon != -1 {
+				// match by regex
+				matchesToken, matchesRemainder := c.regularMatchesPathToken(routeToken, colon, requestToken)
+				if !matchesToken {
+					return false, 0, 0
+				}
+				if matchesRemainder {
+					break
+				}
+			}
+		} else { // no { prefix
+			if requestToken != routeToken {
+				return false, 0, 0
+			}
+			staticCount++
+		}
+	}
+	return true, paramCount, staticCount
+}
+
+// regularMatchesPathToken tests whether the regular expression part of routeToken matches the requestToken or all remaining tokens
+// format routeToken is {someVar:someExpression}, e.g. {zipcode:[\d][\d][\d][\d][A-Z][A-Z]}
+func (c CurlyRouter) regularMatchesPathToken(routeToken string, colon int, requestToken string) (matchesToken bool, matchesRemainder bool) {
+	regPart := routeToken[colon+1 : len(routeToken)-1]
+	if regPart == "*" {
+		if trace {
+			traceLogger.Printf("wildcard parameter detected in route token %s that matches %s\n", routeToken, requestToken)
+		}
+		return true, true
+	}
+	matched, err := regexp.MatchString(regPart, requestToken)
+	return (matched && err == nil), false
+}
+
+var jsr311Router = RouterJSR311{}
+
+// detectRoute selectes from a list of Route the first match by inspecting both the Accept and Content-Type
+// headers of the Request. See also RouterJSR311 in jsr311.go
+func (c CurlyRouter) detectRoute(candidateRoutes sortableCurlyRoutes, httpRequest *http.Request) (*Route, error) {
+	// tracing is done inside detectRoute
+	return jsr311Router.detectRoute(candidateRoutes.routes(), httpRequest)
+}
+
+// detectWebService returns the best matching webService given the list of path tokens.
+// see also computeWebserviceScore
+func (c CurlyRouter) detectWebService(requestTokens []string, webServices []*WebService) *WebService {
+	var best *WebService
+	score := -1
+	for _, each := range webServices {
+		matches, eachScore := c.computeWebserviceScore(requestTokens, each.pathExpr.tokens)
+		if matches && (eachScore > score) {
+			best = each
+			score = eachScore
+		}
+	}
+	return best
+}
+
+// computeWebserviceScore returns whether tokens match and
+// the weighted score of the longest matching consecutive tokens from the beginning.
+func (c CurlyRouter) computeWebserviceScore(requestTokens []string, tokens []string) (bool, int) {
+	if len(tokens) > len(requestTokens) {
+		return false, 0
+	}
+	score := 0
+	for i := 0; i < len(tokens); i++ {
+		each := requestTokens[i]
+		other := tokens[i]
+		if len(each) == 0 && len(other) == 0 {
+			score++
+			continue
+		}
+		if len(other) > 0 && strings.HasPrefix(other, "{") {
+			// no empty match
+			if len(each) == 0 {
+				return false, score
+			}
+			score += 1
+		} else {
+			// not a parameter
+			if each != other {
+				return false, score
+			}
+			score += (len(tokens) - i) * 10 //fuzzy
+		}
+	}
+	return true, score
+}
diff --git a/metrics-server/vendor/github.com/emicklei/go-restful/curly_route.go b/metrics-server/vendor/github.com/emicklei/go-restful/curly_route.go
new file mode 100644
index 0000000..296f946
--- /dev/null
+++ b/metrics-server/vendor/github.com/emicklei/go-restful/curly_route.go
@@ -0,0 +1,52 @@
+package restful
+
+// Copyright 2013 Ernest Micklei. All rights reserved.
+// Use of this source code is governed by a license
+// that can be found in the LICENSE file.
+
+// curlyRoute exits for sorting Routes by the CurlyRouter based on number of parameters and number of static path elements.
+type curlyRoute struct {
+	route       Route
+	paramCount  int
+	staticCount int
+}
+
+type sortableCurlyRoutes []curlyRoute
+
+func (s *sortableCurlyRoutes) add(route curlyRoute) {
+	*s = append(*s, route)
+}
+
+func (s sortableCurlyRoutes) routes() (routes []Route) {
+	for _, each := range s {
+		routes = append(routes, each.route) // TODO change return type
+	}
+	return routes
+}
+
+func (s sortableCurlyRoutes) Len() int {
+	return len(s)
+}
+func (s sortableCurlyRoutes) Swap(i, j int) {
+	s[i], s[j] = s[j], s[i]
+}
+func (s sortableCurlyRoutes) Less(i, j int) bool {
+	ci := s[i]
+	cj := s[j]
+
+	// primary key
+	if ci.staticCount < cj.staticCount {
+		return true
+	}
+	if ci.staticCount > cj.staticCount {
+		return false
+	}
+	// secundary key
+	if ci.paramCount < cj.paramCount {
+		return true
+	}
+	if ci.paramCount > cj.paramCount {
+		return false
+	}
+	return ci.route.Path < cj.route.Path
+}
diff --git a/metrics-server/vendor/github.com/emicklei/go-restful/doc.go b/metrics-server/vendor/github.com/emicklei/go-restful/doc.go
new file mode 100644
index 0000000..f7c16b0
--- /dev/null
+++ b/metrics-server/vendor/github.com/emicklei/go-restful/doc.go
@@ -0,0 +1,185 @@
+/*
+Package restful , a lean package for creating REST-style WebServices without magic.
+
+WebServices and Routes
+
+A WebService has a collection of Route objects that dispatch incoming Http Requests to a function calls.
+Typically, a WebService has a root path (e.g. /users) and defines common MIME types for its routes.
+WebServices must be added to a container (see below) in order to handler Http requests from a server.
+
+A Route is defined by a HTTP method, an URL path and (optionally) the MIME types it consumes (Content-Type) and produces (Accept).
+This package has the logic to find the best matching Route and if found, call its Function.
+
+	ws := new(restful.WebService)
+	ws.
+		Path("/users").
+		Consumes(restful.MIME_JSON, restful.MIME_XML).
+		Produces(restful.MIME_JSON, restful.MIME_XML)
+
+	ws.Route(ws.GET("/{user-id}").To(u.findUser))  // u is a UserResource
+
+	...
+
+	// GET http://localhost:8080/users/1
+	func (u UserResource) findUser(request *restful.Request, response *restful.Response) {
+		id := request.PathParameter("user-id")
+		...
+	}
+
+The (*Request, *Response) arguments provide functions for reading information from the request and writing information back to the response.
+
+See the example https://github.com/emicklei/go-restful/blob/master/examples/restful-user-resource.go with a full implementation.
+
+Regular expression matching Routes
+
+A Route parameter can be specified using the format "uri/{var[:regexp]}" or the special version "uri/{var:*}" for matching the tail of the path.
+For example, /persons/{name:[A-Z][A-Z]} can be used to restrict values for the parameter "name" to only contain capital alphabetic characters.
+Regular expressions must use the standard Go syntax as described in the regexp package. (https://code.google.com/p/re2/wiki/Syntax)
+This feature requires the use of a CurlyRouter.
+
+Containers
+
+A Container holds a collection of WebServices, Filters and a http.ServeMux for multiplexing http requests.
+Using the statements "restful.Add(...) and restful.Filter(...)" will register WebServices and Filters to the Default Container.
+The Default container of go-restful uses the http.DefaultServeMux.
+You can create your own Container and create a new http.Server for that particular container.
+
+	container := restful.NewContainer()
+	server := &http.Server{Addr: ":8081", Handler: container}
+
+Filters
+
+A filter dynamically intercepts requests and responses to transform or use the information contained in the requests or responses.
+You can use filters to perform generic logging, measurement, authentication, redirect, set response headers etc.
+In the restful package there are three hooks into the request,response flow where filters can be added.
+Each filter must define a FilterFunction:
+
+	func (req *restful.Request, resp *restful.Response, chain *restful.FilterChain)
+
+Use the following statement to pass the request,response pair to the next filter or RouteFunction
+
+	chain.ProcessFilter(req, resp)
+
+Container Filters
+
+These are processed before any registered WebService.
+
+	// install a (global) filter for the default container (processed before any webservice)
+	restful.Filter(globalLogging)
+
+WebService Filters
+
+These are processed before any Route of a WebService.
+
+	// install a webservice filter (processed before any route)
+	ws.Filter(webserviceLogging).Filter(measureTime)
+
+
+Route Filters
+
+These are processed before calling the function associated with the Route.
+
+	// install 2 chained route filters (processed before calling findUser)
+	ws.Route(ws.GET("/{user-id}").Filter(routeLogging).Filter(NewCountFilter().routeCounter).To(findUser))
+
+See the example https://github.com/emicklei/go-restful/blob/master/examples/restful-filters.go with full implementations.
+
+Response Encoding
+
+Two encodings are supported: gzip and deflate. To enable this for all responses:
+
+	restful.DefaultContainer.EnableContentEncoding(true)
+
+If a Http request includes the Accept-Encoding header then the response content will be compressed using the specified encoding.
+Alternatively, you can create a Filter that performs the encoding and install it per WebService or Route.
+
+See the example https://github.com/emicklei/go-restful/blob/master/examples/restful-encoding-filter.go
+
+OPTIONS support
+
+By installing a pre-defined container filter, your Webservice(s) can respond to the OPTIONS Http request.
+
+	Filter(OPTIONSFilter())
+
+CORS
+
+By installing the filter of a CrossOriginResourceSharing (CORS), your WebService(s) can handle CORS requests.
+
+	cors := CrossOriginResourceSharing{ExposeHeaders: []string{"X-My-Header"}, CookiesAllowed: false, Container: DefaultContainer}
+	Filter(cors.Filter)
+
+Error Handling
+
+Unexpected things happen. If a request cannot be processed because of a failure, your service needs to tell via the response what happened and why.
+For this reason HTTP status codes exist and it is important to use the correct code in every exceptional situation.
+
+	400: Bad Request
+
+If path or query parameters are not valid (content or type) then use http.StatusBadRequest.
+
+	404: Not Found
+
+Despite a valid URI, the resource requested may not be available
+
+	500: Internal Server Error
+
+If the application logic could not process the request (or write the response) then use http.StatusInternalServerError.
+
+	405: Method Not Allowed
+
+The request has a valid URL but the method (GET,PUT,POST,...) is not allowed.
+
+	406: Not Acceptable
+
+The request does not have or has an unknown Accept Header set for this operation.
+
+	415: Unsupported Media Type
+
+The request does not have or has an unknown Content-Type Header set for this operation.
+
+ServiceError
+
+In addition to setting the correct (error) Http status code, you can choose to write a ServiceError message on the response.
+
+Performance options
+
+This package has several options that affect the performance of your service. It is important to understand them and how you can change it.
+
+	restful.DefaultContainer.DoNotRecover(false)
+
+DoNotRecover controls whether panics will be caught to return HTTP 500.
+If set to false, the container will recover from panics.
+Default value is true
+
+	restful.SetCompressorProvider(NewBoundedCachedCompressors(20, 20))
+
+If content encoding is enabled then the default strategy for getting new gzip/zlib writers and readers is to use a sync.Pool.
+Because writers are expensive structures, performance is even more improved when using a preloaded cache. You can also inject your own implementation.
+
+Trouble shooting
+
+This package has the means to produce detail logging of the complete Http request matching process and filter invocation.
+Enabling this feature requires you to set an implementation of restful.StdLogger (e.g. log.Logger) instance such as:
+
+	restful.TraceLogger(log.New(os.Stdout, "[restful] ", log.LstdFlags|log.Lshortfile))
+
+Logging
+
+The restful.SetLogger() method allows you to override the logger used by the package. By default restful
+uses the standard library `log` package and logs to stdout. Different logging packages are supported as
+long as they conform to `StdLogger` interface defined in the `log` sub-package, writing an adapter for your
+preferred package is simple.
+
+Resources
+
+[project]: https://github.com/emicklei/go-restful
+
+[examples]: https://github.com/emicklei/go-restful/blob/master/examples
+
+[design]:  http://ernestmicklei.com/2012/11/11/go-restful-api-design/
+
+[showcases]: https://github.com/emicklei/mora, https://github.com/emicklei/landskape
+
+(c) 2012-2015, http://ernestmicklei.com. MIT License
+*/
+package restful
diff --git a/metrics-server/vendor/github.com/emicklei/go-restful/entity_accessors.go b/metrics-server/vendor/github.com/emicklei/go-restful/entity_accessors.go
new file mode 100644
index 0000000..66dfc82
--- /dev/null
+++ b/metrics-server/vendor/github.com/emicklei/go-restful/entity_accessors.go
@@ -0,0 +1,162 @@
+package restful
+
+// Copyright 2015 Ernest Micklei. All rights reserved.
+// Use of this source code is governed by a license
+// that can be found in the LICENSE file.
+
+import (
+	"encoding/xml"
+	"strings"
+	"sync"
+)
+
+// EntityReaderWriter can read and write values using an encoding such as JSON,XML.
+type EntityReaderWriter interface {
+	// Read a serialized version of the value from the request.
+	// The Request may have a decompressing reader. Depends on Content-Encoding.
+	Read(req *Request, v interface{}) error
+
+	// Write a serialized version of the value on the response.
+	// The Response may have a compressing writer. Depends on Accept-Encoding.
+	// status should be a valid Http Status code
+	Write(resp *Response, status int, v interface{}) error
+}
+
+// entityAccessRegistry is a singleton
+var entityAccessRegistry = &entityReaderWriters{
+	protection: new(sync.RWMutex),
+	accessors:  map[string]EntityReaderWriter{},
+}
+
+// entityReaderWriters associates MIME to an EntityReaderWriter
+type entityReaderWriters struct {
+	protection *sync.RWMutex
+	accessors  map[string]EntityReaderWriter
+}
+
+func init() {
+	RegisterEntityAccessor(MIME_JSON, NewEntityAccessorJSON(MIME_JSON))
+	RegisterEntityAccessor(MIME_XML, NewEntityAccessorXML(MIME_XML))
+}
+
+// RegisterEntityAccessor add/overrides the ReaderWriter for encoding content with this MIME type.
+func RegisterEntityAccessor(mime string, erw EntityReaderWriter) {
+	entityAccessRegistry.protection.Lock()
+	defer entityAccessRegistry.protection.Unlock()
+	entityAccessRegistry.accessors[mime] = erw
+}
+
+// NewEntityAccessorJSON returns a new EntityReaderWriter for accessing JSON content.
+// This package is already initialized with such an accessor using the MIME_JSON contentType.
+func NewEntityAccessorJSON(contentType string) EntityReaderWriter {
+	return entityJSONAccess{ContentType: contentType}
+}
+
+// NewEntityAccessorXML returns a new EntityReaderWriter for accessing XML content.
+// This package is already initialized with such an accessor using the MIME_XML contentType.
+func NewEntityAccessorXML(contentType string) EntityReaderWriter {
+	return entityXMLAccess{ContentType: contentType}
+}
+
+// accessorAt returns the registered ReaderWriter for this MIME type.
+func (r *entityReaderWriters) accessorAt(mime string) (EntityReaderWriter, bool) {
+	r.protection.RLock()
+	defer r.protection.RUnlock()
+	er, ok := r.accessors[mime]
+	if !ok {
+		// retry with reverse lookup
+		// more expensive but we are in an exceptional situation anyway
+		for k, v := range r.accessors {
+			if strings.Contains(mime, k) {
+				return v, true
+			}
+		}
+	}
+	return er, ok
+}
+
+// entityXMLAccess is a EntityReaderWriter for XML encoding
+type entityXMLAccess struct {
+	// This is used for setting the Content-Type header when writing
+	ContentType string
+}
+
+// Read unmarshalls the value from XML
+func (e entityXMLAccess) Read(req *Request, v interface{}) error {
+	return xml.NewDecoder(req.Request.Body).Decode(v)
+}
+
+// Write marshalls the value to JSON and set the Content-Type Header.
+func (e entityXMLAccess) Write(resp *Response, status int, v interface{}) error {
+	return writeXML(resp, status, e.ContentType, v)
+}
+
+// writeXML marshalls the value to JSON and set the Content-Type Header.
+func writeXML(resp *Response, status int, contentType string, v interface{}) error {
+	if v == nil {
+		resp.WriteHeader(status)
+		// do not write a nil representation
+		return nil
+	}
+	if resp.prettyPrint {
+		// pretty output must be created and written explicitly
+		output, err := xml.MarshalIndent(v, " ", " ")
+		if err != nil {
+			return err
+		}
+		resp.Header().Set(HEADER_ContentType, contentType)
+		resp.WriteHeader(status)
+		_, err = resp.Write([]byte(xml.Header))
+		if err != nil {
+			return err
+		}
+		_, err = resp.Write(output)
+		return err
+	}
+	// not-so-pretty
+	resp.Header().Set(HEADER_ContentType, contentType)
+	resp.WriteHeader(status)
+	return xml.NewEncoder(resp).Encode(v)
+}
+
+// entityJSONAccess is a EntityReaderWriter for JSON encoding
+type entityJSONAccess struct {
+	// This is used for setting the Content-Type header when writing
+	ContentType string
+}
+
+// Read unmarshalls the value from JSON
+func (e entityJSONAccess) Read(req *Request, v interface{}) error {
+	decoder := NewDecoder(req.Request.Body)
+	decoder.UseNumber()
+	return decoder.Decode(v)
+}
+
+// Write marshalls the value to JSON and set the Content-Type Header.
+func (e entityJSONAccess) Write(resp *Response, status int, v interface{}) error {
+	return writeJSON(resp, status, e.ContentType, v)
+}
+
+// write marshalls the value to JSON and set the Content-Type Header.
+func writeJSON(resp *Response, status int, contentType string, v interface{}) error {
+	if v == nil {
+		resp.WriteHeader(status)
+		// do not write a nil representation
+		return nil
+	}
+	if resp.prettyPrint {
+		// pretty output must be created and written explicitly
+		output, err := MarshalIndent(v, "", " ")
+		if err != nil {
+			return err
+		}
+		resp.Header().Set(HEADER_ContentType, contentType)
+		resp.WriteHeader(status)
+		_, err = resp.Write(output)
+		return err
+	}
+	// not-so-pretty
+	resp.Header().Set(HEADER_ContentType, contentType)
+	resp.WriteHeader(status)
+	return NewEncoder(resp).Encode(v)
+}
diff --git a/metrics-server/vendor/github.com/emicklei/go-restful/filter.go b/metrics-server/vendor/github.com/emicklei/go-restful/filter.go
new file mode 100644
index 0000000..c23bfb5
--- /dev/null
+++ b/metrics-server/vendor/github.com/emicklei/go-restful/filter.go
@@ -0,0 +1,35 @@
+package restful
+
+// Copyright 2013 Ernest Micklei. All rights reserved.
+// Use of this source code is governed by a license
+// that can be found in the LICENSE file.
+
+// FilterChain is a request scoped object to process one or more filters before calling the target RouteFunction.
+type FilterChain struct {
+	Filters []FilterFunction // ordered list of FilterFunction
+	Index   int              // index into filters that is currently in progress
+	Target  RouteFunction    // function to call after passing all filters
+}
+
+// ProcessFilter passes the request,response pair through the next of Filters.
+// Each filter can decide to proceed to the next Filter or handle the Response itself.
+func (f *FilterChain) ProcessFilter(request *Request, response *Response) {
+	if f.Index < len(f.Filters) {
+		f.Index++
+		f.Filters[f.Index-1](request, response, f)
+	} else {
+		f.Target(request, response)
+	}
+}
+
+// FilterFunction definitions must call ProcessFilter on the FilterChain to pass on the control and eventually call the RouteFunction
+type FilterFunction func(*Request, *Response, *FilterChain)
+
+// NoBrowserCacheFilter is a filter function to set HTTP headers that disable browser caching
+// See examples/restful-no-cache-filter.go for usage
+func NoBrowserCacheFilter(req *Request, resp *Response, chain *FilterChain) {
+	resp.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate") // HTTP 1.1.
+	resp.Header().Set("Pragma", "no-cache")                                   // HTTP 1.0.
+	resp.Header().Set("Expires", "0")                                         // Proxies.
+	chain.ProcessFilter(req, resp)
+}
diff --git a/metrics-server/vendor/github.com/emicklei/go-restful/json.go b/metrics-server/vendor/github.com/emicklei/go-restful/json.go
new file mode 100644
index 0000000..8711651
--- /dev/null
+++ b/metrics-server/vendor/github.com/emicklei/go-restful/json.go
@@ -0,0 +1,11 @@
+// +build !jsoniter
+
+package restful
+
+import "encoding/json"
+
+var (
+	MarshalIndent = json.MarshalIndent
+	NewDecoder    = json.NewDecoder
+	NewEncoder    = json.NewEncoder
+)
diff --git a/metrics-server/vendor/github.com/emicklei/go-restful/jsoniter.go b/metrics-server/vendor/github.com/emicklei/go-restful/jsoniter.go
new file mode 100644
index 0000000..11b8f8a
--- /dev/null
+++ b/metrics-server/vendor/github.com/emicklei/go-restful/jsoniter.go
@@ -0,0 +1,12 @@
+// +build jsoniter
+
+package restful
+
+import "github.com/json-iterator/go"
+
+var (
+	json          = jsoniter.ConfigCompatibleWithStandardLibrary
+	MarshalIndent = json.MarshalIndent
+	NewDecoder    = json.NewDecoder
+	NewEncoder    = json.NewEncoder
+)
diff --git a/metrics-server/vendor/github.com/emicklei/go-restful/jsr311.go b/metrics-server/vendor/github.com/emicklei/go-restful/jsr311.go
new file mode 100644
index 0000000..4360b49
--- /dev/null
+++ b/metrics-server/vendor/github.com/emicklei/go-restful/jsr311.go
@@ -0,0 +1,293 @@
+package restful
+
+// Copyright 2013 Ernest Micklei. All rights reserved.
+// Use of this source code is governed by a license
+// that can be found in the LICENSE file.
+
+import (
+	"errors"
+	"fmt"
+	"net/http"
+	"sort"
+)
+
+// RouterJSR311 implements the flow for matching Requests to Routes (and consequently Resource Functions)
+// as specified by the JSR311 http://jsr311.java.net/nonav/releases/1.1/spec/spec.html.
+// RouterJSR311 implements the Router interface.
+// Concept of locators is not implemented.
+type RouterJSR311 struct{}
+
+// SelectRoute is part of the Router interface and returns the best match
+// for the WebService and its Route for the given Request.
+func (r RouterJSR311) SelectRoute(
+	webServices []*WebService,
+	httpRequest *http.Request) (selectedService *WebService, selectedRoute *Route, err error) {
+
+	// Identify the root resource class (WebService)
+	dispatcher, finalMatch, err := r.detectDispatcher(httpRequest.URL.Path, webServices)
+	if err != nil {
+		return nil, nil, NewError(http.StatusNotFound, "")
+	}
+	// Obtain the set of candidate methods (Routes)
+	routes := r.selectRoutes(dispatcher, finalMatch)
+	if len(routes) == 0 {
+		return dispatcher, nil, NewError(http.StatusNotFound, "404: Page Not Found")
+	}
+
+	// Identify the method (Route) that will handle the request
+	route, ok := r.detectRoute(routes, httpRequest)
+	return dispatcher, route, ok
+}
+
+// ExtractParameters is used to obtain the path parameters from the route using the same matching
+// engine as the JSR 311 router.
+func (r RouterJSR311) ExtractParameters(route *Route, webService *WebService, urlPath string) map[string]string {
+	webServiceExpr := webService.pathExpr
+	webServiceMatches := webServiceExpr.Matcher.FindStringSubmatch(urlPath)
+	pathParameters := r.extractParams(webServiceExpr, webServiceMatches)
+	routeExpr := route.pathExpr
+	routeMatches := routeExpr.Matcher.FindStringSubmatch(webServiceMatches[len(webServiceMatches)-1])
+	routeParams := r.extractParams(routeExpr, routeMatches)
+	for key, value := range routeParams {
+		pathParameters[key] = value
+	}
+	return pathParameters
+}
+
+func (RouterJSR311) extractParams(pathExpr *pathExpression, matches []string) map[string]string {
+	params := map[string]string{}
+	for i := 1; i < len(matches); i++ {
+		if len(pathExpr.VarNames) >= i {
+			params[pathExpr.VarNames[i-1]] = matches[i]
+		}
+	}
+	return params
+}
+
+// http://jsr311.java.net/nonav/releases/1.1/spec/spec3.html#x3-360003.7.2
+func (r RouterJSR311) detectRoute(routes []Route, httpRequest *http.Request) (*Route, error) {
+	ifOk := []Route{}
+	for _, each := range routes {
+		ok := true
+		for _, fn := range each.If {
+			if !fn(httpRequest) {
+				ok = false
+				break
+			}
+		}
+		if ok {
+			ifOk = append(ifOk, each)
+		}
+	}
+	if len(ifOk) == 0 {
+		if trace {
+			traceLogger.Printf("no Route found (from %d) that passes conditional checks", len(routes))
+		}
+		return nil, NewError(http.StatusNotFound, "404: Not Found")
+	}
+
+	// http method
+	methodOk := []Route{}
+	for _, each := range ifOk {
+		if httpRequest.Method == each.Method {
+			methodOk = append(methodOk, each)
+		}
+	}
+	if len(methodOk) == 0 {
+		if trace {
+			traceLogger.Printf("no Route found (in %d routes) that matches HTTP method %s\n", len(routes), httpRequest.Method)
+		}
+		return nil, NewError(http.StatusMethodNotAllowed, "405: Method Not Allowed")
+	}
+	inputMediaOk := methodOk
+
+	// content-type
+	contentType := httpRequest.Header.Get(HEADER_ContentType)
+	inputMediaOk = []Route{}
+	for _, each := range methodOk {
+		if each.matchesContentType(contentType) {
+			inputMediaOk = append(inputMediaOk, each)
+		}
+	}
+	if len(inputMediaOk) == 0 {
+		if trace {
+			traceLogger.Printf("no Route found (from %d) that matches HTTP Content-Type: %s\n", len(methodOk), contentType)
+		}
+		return nil, NewError(http.StatusUnsupportedMediaType, "415: Unsupported Media Type")
+	}
+
+	// accept
+	outputMediaOk := []Route{}
+	accept := httpRequest.Header.Get(HEADER_Accept)
+	if len(accept) == 0 {
+		accept = "*/*"
+	}
+	for _, each := range inputMediaOk {
+		if each.matchesAccept(accept) {
+			outputMediaOk = append(outputMediaOk, each)
+		}
+	}
+	if len(outputMediaOk) == 0 {
+		if trace {
+			traceLogger.Printf("no Route found (from %d) that matches HTTP Accept: %s\n", len(inputMediaOk), accept)
+		}
+		return nil, NewError(http.StatusNotAcceptable, "406: Not Acceptable")
+	}
+	// return r.bestMatchByMedia(outputMediaOk, contentType, accept), nil
+	return &outputMediaOk[0], nil
+}
+
+// http://jsr311.java.net/nonav/releases/1.1/spec/spec3.html#x3-360003.7.2
+// n/m > n/* > */*
+func (r RouterJSR311) bestMatchByMedia(routes []Route, contentType string, accept string) *Route {
+	// TODO
+	return &routes[0]
+}
+
+// http://jsr311.java.net/nonav/releases/1.1/spec/spec3.html#x3-360003.7.2  (step 2)
+func (r RouterJSR311) selectRoutes(dispatcher *WebService, pathRemainder string) []Route {
+	filtered := &sortableRouteCandidates{}
+	for _, each := range dispatcher.Routes() {
+		pathExpr := each.pathExpr
+		matches := pathExpr.Matcher.FindStringSubmatch(pathRemainder)
+		if matches != nil {
+			lastMatch := matches[len(matches)-1]
+			if len(lastMatch) == 0 || lastMatch == "/" { // do not include if value is neither empty nor ‘/’.
+				filtered.candidates = append(filtered.candidates,
+					routeCandidate{each, len(matches) - 1, pathExpr.LiteralCount, pathExpr.VarCount})
+			}
+		}
+	}
+	if len(filtered.candidates) == 0 {
+		if trace {
+			traceLogger.Printf("WebService on path %s has no routes that match URL path remainder:%s\n", dispatcher.rootPath, pathRemainder)
+		}
+		return []Route{}
+	}
+	sort.Sort(sort.Reverse(filtered))
+
+	// select other routes from candidates whoes expression matches rmatch
+	matchingRoutes := []Route{filtered.candidates[0].route}
+	for c := 1; c < len(filtered.candidates); c++ {
+		each := filtered.candidates[c]
+		if each.route.pathExpr.Matcher.MatchString(pathRemainder) {
+			matchingRoutes = append(matchingRoutes, each.route)
+		}
+	}
+	return matchingRoutes
+}
+
+// http://jsr311.java.net/nonav/releases/1.1/spec/spec3.html#x3-360003.7.2 (step 1)
+func (r RouterJSR311) detectDispatcher(requestPath string, dispatchers []*WebService) (*WebService, string, error) {
+	filtered := &sortableDispatcherCandidates{}
+	for _, each := range dispatchers {
+		matches := each.pathExpr.Matcher.FindStringSubmatch(requestPath)
+		if matches != nil {
+			filtered.candidates = append(filtered.candidates,
+				dispatcherCandidate{each, matches[len(matches)-1], len(matches), each.pathExpr.LiteralCount, each.pathExpr.VarCount})
+		}
+	}
+	if len(filtered.candidates) == 0 {
+		if trace {
+			traceLogger.Printf("no WebService was found to match URL path:%s\n", requestPath)
+		}
+		return nil, "", errors.New("not found")
+	}
+	sort.Sort(sort.Reverse(filtered))
+	return filtered.candidates[0].dispatcher, filtered.candidates[0].finalMatch, nil
+}
+
+// Types and functions to support the sorting of Routes
+
+type routeCandidate struct {
+	route           Route
+	matchesCount    int // the number of capturing groups
+	literalCount    int // the number of literal characters (means those not resulting from template variable substitution)
+	nonDefaultCount int // the number of capturing groups with non-default regular expressions (i.e. not ‘([^  /]+?)’)
+}
+
+func (r routeCandidate) expressionToMatch() string {
+	return r.route.pathExpr.Source
+}
+
+func (r routeCandidate) String() string {
+	return fmt.Sprintf("(m=%d,l=%d,n=%d)", r.matchesCount, r.literalCount, r.nonDefaultCount)
+}
+
+type sortableRouteCandidates struct {
+	candidates []routeCandidate
+}
+
+func (rcs *sortableRouteCandidates) Len() int {
+	return len(rcs.candidates)
+}
+func (rcs *sortableRouteCandidates) Swap(i, j int) {
+	rcs.candidates[i], rcs.candidates[j] = rcs.candidates[j], rcs.candidates[i]
+}
+func (rcs *sortableRouteCandidates) Less(i, j int) bool {
+	ci := rcs.candidates[i]
+	cj := rcs.candidates[j]
+	// primary key
+	if ci.literalCount < cj.literalCount {
+		return true
+	}
+	if ci.literalCount > cj.literalCount {
+		return false
+	}
+	// secundary key
+	if ci.matchesCount < cj.matchesCount {
+		return true
+	}
+	if ci.matchesCount > cj.matchesCount {
+		return false
+	}
+	// tertiary key
+	if ci.nonDefaultCount < cj.nonDefaultCount {
+		return true
+	}
+	if ci.nonDefaultCount > cj.nonDefaultCount {
+		return false
+	}
+	// quaternary key ("source" is interpreted as Path)
+	return ci.route.Path < cj.route.Path
+}
+
+// Types and functions to support the sorting of Dispatchers
+
+type dispatcherCandidate struct {
+	dispatcher      *WebService
+	finalMatch      string
+	matchesCount    int // the number of capturing groups
+	literalCount    int // the number of literal characters (means those not resulting from template variable substitution)
+	nonDefaultCount int // the number of capturing groups with non-default regular expressions (i.e. not ‘([^  /]+?)’)
+}
+type sortableDispatcherCandidates struct {
+	candidates []dispatcherCandidate
+}
+
+func (dc *sortableDispatcherCandidates) Len() int {
+	return len(dc.candidates)
+}
+func (dc *sortableDispatcherCandidates) Swap(i, j int) {
+	dc.candidates[i], dc.candidates[j] = dc.candidates[j], dc.candidates[i]
+}
+func (dc *sortableDispatcherCandidates) Less(i, j int) bool {
+	ci := dc.candidates[i]
+	cj := dc.candidates[j]
+	// primary key
+	if ci.matchesCount < cj.matchesCount {
+		return true
+	}
+	if ci.matchesCount > cj.matchesCount {
+		return false
+	}
+	// secundary key
+	if ci.literalCount < cj.literalCount {
+		return true
+	}
+	if ci.literalCount > cj.literalCount {
+		return false
+	}
+	// tertiary key
+	return ci.nonDefaultCount < cj.nonDefaultCount
+}
diff --git a/metrics-server/vendor/github.com/emicklei/go-restful/log/log.go b/metrics-server/vendor/github.com/emicklei/go-restful/log/log.go
new file mode 100644
index 0000000..6cd44c7
--- /dev/null
+++ b/metrics-server/vendor/github.com/emicklei/go-restful/log/log.go
@@ -0,0 +1,34 @@
+package log
+
+import (
+	stdlog "log"
+	"os"
+)
+
+// StdLogger corresponds to a minimal subset of the interface satisfied by stdlib log.Logger
+type StdLogger interface {
+	Print(v ...interface{})
+	Printf(format string, v ...interface{})
+}
+
+var Logger StdLogger
+
+func init() {
+	// default Logger
+	SetLogger(stdlog.New(os.Stderr, "[restful] ", stdlog.LstdFlags|stdlog.Lshortfile))
+}
+
+// SetLogger sets the logger for this package
+func SetLogger(customLogger StdLogger) {
+	Logger = customLogger
+}
+
+// Print delegates to the Logger
+func Print(v ...interface{}) {
+	Logger.Print(v...)
+}
+
+// Printf delegates to the Logger
+func Printf(format string, v ...interface{}) {
+	Logger.Printf(format, v...)
+}
diff --git a/metrics-server/vendor/github.com/emicklei/go-restful/logger.go b/metrics-server/vendor/github.com/emicklei/go-restful/logger.go
new file mode 100644
index 0000000..6595df0
--- /dev/null
+++ b/metrics-server/vendor/github.com/emicklei/go-restful/logger.go
@@ -0,0 +1,32 @@
+package restful
+
+// Copyright 2014 Ernest Micklei. All rights reserved.
+// Use of this source code is governed by a license
+// that can be found in the LICENSE file.
+import (
+	"github.com/emicklei/go-restful/log"
+)
+
+var trace bool = false
+var traceLogger log.StdLogger
+
+func init() {
+	traceLogger = log.Logger // use the package logger by default
+}
+
+// TraceLogger enables detailed logging of Http request matching and filter invocation. Default no logger is set.
+// You may call EnableTracing() directly to enable trace logging to the package-wide logger.
+func TraceLogger(logger log.StdLogger) {
+	traceLogger = logger
+	EnableTracing(logger != nil)
+}
+
+// SetLogger exposes the setter for the global logger on the top-level package
+func SetLogger(customLogger log.StdLogger) {
+	log.SetLogger(customLogger)
+}
+
+// EnableTracing can be used to Trace logging on and off.
+func EnableTracing(enabled bool) {
+	trace = enabled
+}
diff --git a/metrics-server/vendor/github.com/emicklei/go-restful/mime.go b/metrics-server/vendor/github.com/emicklei/go-restful/mime.go
new file mode 100644
index 0000000..d7ea2b6
--- /dev/null
+++ b/metrics-server/vendor/github.com/emicklei/go-restful/mime.go
@@ -0,0 +1,45 @@
+package restful
+
+import (
+	"strconv"
+	"strings"
+)
+
+type mime struct {
+	media   string
+	quality float64
+}
+
+// insertMime adds a mime to a list and keeps it sorted by quality.
+func insertMime(l []mime, e mime) []mime {
+	for i, each := range l {
+		// if current mime has lower quality then insert before
+		if e.quality > each.quality {
+			left := append([]mime{}, l[0:i]...)
+			return append(append(left, e), l[i:]...)
+		}
+	}
+	return append(l, e)
+}
+
+// sortedMimes returns a list of mime sorted (desc) by its specified quality.
+func sortedMimes(accept string) (sorted []mime) {
+	for _, each := range strings.Split(accept, ",") {
+		typeAndQuality := strings.Split(strings.Trim(each, " "), ";")
+		if len(typeAndQuality) == 1 {
+			sorted = insertMime(sorted, mime{typeAndQuality[0], 1.0})
+		} else {
+			// take factor
+			parts := strings.Split(typeAndQuality[1], "=")
+			if len(parts) == 2 {
+				f, err := strconv.ParseFloat(parts[1], 64)
+				if err != nil {
+					traceLogger.Printf("unable to parse quality in %s, %v", each, err)
+				} else {
+					sorted = insertMime(sorted, mime{typeAndQuality[0], f})
+				}
+			}
+		}
+	}
+	return
+}
diff --git a/metrics-server/vendor/github.com/emicklei/go-restful/options_filter.go b/metrics-server/vendor/github.com/emicklei/go-restful/options_filter.go
new file mode 100644
index 0000000..5c1b342
--- /dev/null
+++ b/metrics-server/vendor/github.com/emicklei/go-restful/options_filter.go
@@ -0,0 +1,34 @@
+package restful
+
+import "strings"
+
+// Copyright 2013 Ernest Micklei. All rights reserved.
+// Use of this source code is governed by a license
+// that can be found in the LICENSE file.
+
+// OPTIONSFilter is a filter function that inspects the Http Request for the OPTIONS method
+// and provides the response with a set of allowed methods for the request URL Path.
+// As for any filter, you can also install it for a particular WebService within a Container.
+// Note: this filter is not needed when using CrossOriginResourceSharing (for CORS).
+func (c *Container) OPTIONSFilter(req *Request, resp *Response, chain *FilterChain) {
+	if "OPTIONS" != req.Request.Method {
+		chain.ProcessFilter(req, resp)
+		return
+	}
+
+	archs := req.Request.Header.Get(HEADER_AccessControlRequestHeaders)
+	methods := strings.Join(c.computeAllowedMethods(req), ",")
+	origin := req.Request.Header.Get(HEADER_Origin)
+
+	resp.AddHeader(HEADER_Allow, methods)
+	resp.AddHeader(HEADER_AccessControlAllowOrigin, origin)
+	resp.AddHeader(HEADER_AccessControlAllowHeaders, archs)
+	resp.AddHeader(HEADER_AccessControlAllowMethods, methods)
+}
+
+// OPTIONSFilter is a filter function that inspects the Http Request for the OPTIONS method
+// and provides the response with a set of allowed methods for the request URL Path.
+// Note: this filter is not needed when using CrossOriginResourceSharing (for CORS).
+func OPTIONSFilter() FilterFunction {
+	return DefaultContainer.OPTIONSFilter
+}
diff --git a/metrics-server/vendor/github.com/emicklei/go-restful/parameter.go b/metrics-server/vendor/github.com/emicklei/go-restful/parameter.go
new file mode 100644
index 0000000..e879330
--- /dev/null
+++ b/metrics-server/vendor/github.com/emicklei/go-restful/parameter.go
@@ -0,0 +1,143 @@
+package restful
+
+// Copyright 2013 Ernest Micklei. All rights reserved.
+// Use of this source code is governed by a license
+// that can be found in the LICENSE file.
+
+const (
+	// PathParameterKind = indicator of Request parameter type "path"
+	PathParameterKind = iota
+
+	// QueryParameterKind = indicator of Request parameter type "query"
+	QueryParameterKind
+
+	// BodyParameterKind = indicator of Request parameter type "body"
+	BodyParameterKind
+
+	// HeaderParameterKind = indicator of Request parameter type "header"
+	HeaderParameterKind
+
+	// FormParameterKind = indicator of Request parameter type "form"
+	FormParameterKind
+
+	// CollectionFormatCSV comma separated values `foo,bar`
+	CollectionFormatCSV = CollectionFormat("csv")
+
+	// CollectionFormatSSV space separated values `foo bar`
+	CollectionFormatSSV = CollectionFormat("ssv")
+
+	// CollectionFormatTSV tab separated values `foo\tbar`
+	CollectionFormatTSV = CollectionFormat("tsv")
+
+	// CollectionFormatPipes pipe separated values `foo|bar`
+	CollectionFormatPipes = CollectionFormat("pipes")
+
+	// CollectionFormatMulti corresponds to multiple parameter instances instead of multiple values for a single
+	// instance `foo=bar&foo=baz`. This is valid only for QueryParameters and FormParameters
+	CollectionFormatMulti = CollectionFormat("multi")
+)
+
+type CollectionFormat string
+
+func (cf CollectionFormat) String() string {
+	return string(cf)
+}
+
+// Parameter is for documententing the parameter used in a Http Request
+// ParameterData kinds are Path,Query and Body
+type Parameter struct {
+	data *ParameterData
+}
+
+// ParameterData represents the state of a Parameter.
+// It is made public to make it accessible to e.g. the Swagger package.
+type ParameterData struct {
+	Name, Description, DataType, DataFormat string
+	Kind                                    int
+	Required                                bool
+	AllowableValues                         map[string]string
+	AllowMultiple                           bool
+	DefaultValue                            string
+	CollectionFormat                        string
+}
+
+// Data returns the state of the Parameter
+func (p *Parameter) Data() ParameterData {
+	return *p.data
+}
+
+// Kind returns the parameter type indicator (see const for valid values)
+func (p *Parameter) Kind() int {
+	return p.data.Kind
+}
+
+func (p *Parameter) bePath() *Parameter {
+	p.data.Kind = PathParameterKind
+	return p
+}
+func (p *Parameter) beQuery() *Parameter {
+	p.data.Kind = QueryParameterKind
+	return p
+}
+func (p *Parameter) beBody() *Parameter {
+	p.data.Kind = BodyParameterKind
+	return p
+}
+
+func (p *Parameter) beHeader() *Parameter {
+	p.data.Kind = HeaderParameterKind
+	return p
+}
+
+func (p *Parameter) beForm() *Parameter {
+	p.data.Kind = FormParameterKind
+	return p
+}
+
+// Required sets the required field and returns the receiver
+func (p *Parameter) Required(required bool) *Parameter {
+	p.data.Required = required
+	return p
+}
+
+// AllowMultiple sets the allowMultiple field and returns the receiver
+func (p *Parameter) AllowMultiple(multiple bool) *Parameter {
+	p.data.AllowMultiple = multiple
+	return p
+}
+
+// AllowableValues sets the allowableValues field and returns the receiver
+func (p *Parameter) AllowableValues(values map[string]string) *Parameter {
+	p.data.AllowableValues = values
+	return p
+}
+
+// DataType sets the dataType field and returns the receiver
+func (p *Parameter) DataType(typeName string) *Parameter {
+	p.data.DataType = typeName
+	return p
+}
+
+// DataFormat sets the dataFormat field for Swagger UI
+func (p *Parameter) DataFormat(formatName string) *Parameter {
+	p.data.DataFormat = formatName
+	return p
+}
+
+// DefaultValue sets the default value field and returns the receiver
+func (p *Parameter) DefaultValue(stringRepresentation string) *Parameter {
+	p.data.DefaultValue = stringRepresentation
+	return p
+}
+
+// Description sets the description value field and returns the receiver
+func (p *Parameter) Description(doc string) *Parameter {
+	p.data.Description = doc
+	return p
+}
+
+// CollectionFormat sets the collection format for an array type
+func (p *Parameter) CollectionFormat(format CollectionFormat) *Parameter {
+	p.data.CollectionFormat = format.String()
+	return p
+}
diff --git a/metrics-server/vendor/github.com/emicklei/go-restful/path_expression.go b/metrics-server/vendor/github.com/emicklei/go-restful/path_expression.go
new file mode 100644
index 0000000..95a9a25
--- /dev/null
+++ b/metrics-server/vendor/github.com/emicklei/go-restful/path_expression.go
@@ -0,0 +1,74 @@
+package restful
+
+// Copyright 2013 Ernest Micklei. All rights reserved.
+// Use of this source code is governed by a license
+// that can be found in the LICENSE file.
+
+import (
+	"bytes"
+	"fmt"
+	"regexp"
+	"strings"
+)
+
+// PathExpression holds a compiled path expression (RegExp) needed to match against
+// Http request paths and to extract path parameter values.
+type pathExpression struct {
+	LiteralCount int      // the number of literal characters (means those not resulting from template variable substitution)
+	VarNames     []string // the names of parameters (enclosed by {}) in the path
+	VarCount     int      // the number of named parameters (enclosed by {}) in the path
+	Matcher      *regexp.Regexp
+	Source       string // Path as defined by the RouteBuilder
+	tokens       []string
+}
+
+// NewPathExpression creates a PathExpression from the input URL path.
+// Returns an error if the path is invalid.
+func newPathExpression(path string) (*pathExpression, error) {
+	expression, literalCount, varNames, varCount, tokens := templateToRegularExpression(path)
+	compiled, err := regexp.Compile(expression)
+	if err != nil {
+		return nil, err
+	}
+	return &pathExpression{literalCount, varNames, varCount, compiled, expression, tokens}, nil
+}
+
+// http://jsr311.java.net/nonav/releases/1.1/spec/spec3.html#x3-370003.7.3
+func templateToRegularExpression(template string) (expression string, literalCount int, varNames []string, varCount int, tokens []string) {
+	var buffer bytes.Buffer
+	buffer.WriteString("^")
+	//tokens = strings.Split(template, "/")
+	tokens = tokenizePath(template)
+	for _, each := range tokens {
+		if each == "" {
+			continue
+		}
+		buffer.WriteString("/")
+		if strings.HasPrefix(each, "{") {
+			// check for regular expression in variable
+			colon := strings.Index(each, ":")
+			var varName string
+			if colon != -1 {
+				// extract expression
+				varName = strings.TrimSpace(each[1:colon])
+				paramExpr := strings.TrimSpace(each[colon+1 : len(each)-1])
+				if paramExpr == "*" { // special case
+					buffer.WriteString("(.*)")
+				} else {
+					buffer.WriteString(fmt.Sprintf("(%s)", paramExpr)) // between colon and closing moustache
+				}
+			} else {
+				// plain var
+				varName = strings.TrimSpace(each[1 : len(each)-1])
+				buffer.WriteString("([^/]+?)")
+			}
+			varNames = append(varNames, varName)
+			varCount += 1
+		} else {
+			literalCount += len(each)
+			encoded := each // TODO URI encode
+			buffer.WriteString(regexp.QuoteMeta(encoded))
+		}
+	}
+	return strings.TrimRight(buffer.String(), "/") + "(/.*)?$", literalCount, varNames, varCount, tokens
+}
diff --git a/metrics-server/vendor/github.com/emicklei/go-restful/path_processor.go b/metrics-server/vendor/github.com/emicklei/go-restful/path_processor.go
new file mode 100644
index 0000000..357c723
--- /dev/null
+++ b/metrics-server/vendor/github.com/emicklei/go-restful/path_processor.go
@@ -0,0 +1,63 @@
+package restful
+
+import (
+	"bytes"
+	"strings"
+)
+
+// Copyright 2018 Ernest Micklei. All rights reserved.
+// Use of this source code is governed by a license
+// that can be found in the LICENSE file.
+
+// PathProcessor is extra behaviour that a Router can provide to extract path parameters from the path.
+// If a Router does not implement this interface then the default behaviour will be used.
+type PathProcessor interface {
+	// ExtractParameters gets the path parameters defined in the route and webService from the urlPath
+	ExtractParameters(route *Route, webService *WebService, urlPath string) map[string]string
+}
+
+type defaultPathProcessor struct{}
+
+// Extract the parameters from the request url path
+func (d defaultPathProcessor) ExtractParameters(r *Route, _ *WebService, urlPath string) map[string]string {
+	urlParts := tokenizePath(urlPath)
+	pathParameters := map[string]string{}
+	for i, key := range r.pathParts {
+		var value string
+		if i >= len(urlParts) {
+			value = ""
+		} else {
+			value = urlParts[i]
+		}
+		if strings.HasPrefix(key, "{") { // path-parameter
+			if colon := strings.Index(key, ":"); colon != -1 {
+				// extract by regex
+				regPart := key[colon+1 : len(key)-1]
+				keyPart := key[1:colon]
+				if regPart == "*" {
+					pathParameters[keyPart] = untokenizePath(i, urlParts)
+					break
+				} else {
+					pathParameters[keyPart] = value
+				}
+			} else {
+				// without enclosing {}
+				pathParameters[key[1:len(key)-1]] = value
+			}
+		}
+	}
+	return pathParameters
+}
+
+// Untokenize back into an URL path using the slash separator
+func untokenizePath(offset int, parts []string) string {
+	var buffer bytes.Buffer
+	for p := offset; p < len(parts); p++ {
+		buffer.WriteString(parts[p])
+		// do not end
+		if p < len(parts)-1 {
+			buffer.WriteString("/")
+		}
+	}
+	return buffer.String()
+}
diff --git a/metrics-server/vendor/github.com/emicklei/go-restful/request.go b/metrics-server/vendor/github.com/emicklei/go-restful/request.go
new file mode 100644
index 0000000..a20730f
--- /dev/null
+++ b/metrics-server/vendor/github.com/emicklei/go-restful/request.go
@@ -0,0 +1,118 @@
+package restful
+
+// Copyright 2013 Ernest Micklei. All rights reserved.
+// Use of this source code is governed by a license
+// that can be found in the LICENSE file.
+
+import (
+	"compress/zlib"
+	"net/http"
+)
+
+var defaultRequestContentType string
+
+// Request is a wrapper for a http Request that provides convenience methods
+type Request struct {
+	Request           *http.Request
+	pathParameters    map[string]string
+	attributes        map[string]interface{} // for storing request-scoped values
+	selectedRoutePath string                 // root path + route path that matched the request, e.g. /meetings/{id}/attendees
+}
+
+func NewRequest(httpRequest *http.Request) *Request {
+	return &Request{
+		Request:        httpRequest,
+		pathParameters: map[string]string{},
+		attributes:     map[string]interface{}{},
+	} // empty parameters, attributes
+}
+
+// If ContentType is missing or */* is given then fall back to this type, otherwise
+// a "Unable to unmarshal content of type:" response is returned.
+// Valid values are restful.MIME_JSON and restful.MIME_XML
+// Example:
+// 	restful.DefaultRequestContentType(restful.MIME_JSON)
+func DefaultRequestContentType(mime string) {
+	defaultRequestContentType = mime
+}
+
+// PathParameter accesses the Path parameter value by its name
+func (r *Request) PathParameter(name string) string {
+	return r.pathParameters[name]
+}
+
+// PathParameters accesses the Path parameter values
+func (r *Request) PathParameters() map[string]string {
+	return r.pathParameters
+}
+
+// QueryParameter returns the (first) Query parameter value by its name
+func (r *Request) QueryParameter(name string) string {
+	return r.Request.FormValue(name)
+}
+
+// QueryParameters returns the all the query parameters values by name
+func (r *Request) QueryParameters(name string) []string {
+	return r.Request.URL.Query()[name]
+}
+
+// BodyParameter parses the body of the request (once for typically a POST or a PUT) and returns the value of the given name or an error.
+func (r *Request) BodyParameter(name string) (string, error) {
+	err := r.Request.ParseForm()
+	if err != nil {
+		return "", err
+	}
+	return r.Request.PostFormValue(name), nil
+}
+
+// HeaderParameter returns the HTTP Header value of a Header name or empty if missing
+func (r *Request) HeaderParameter(name string) string {
+	return r.Request.Header.Get(name)
+}
+
+// ReadEntity checks the Accept header and reads the content into the entityPointer.
+func (r *Request) ReadEntity(entityPointer interface{}) (err error) {
+	contentType := r.Request.Header.Get(HEADER_ContentType)
+	contentEncoding := r.Request.Header.Get(HEADER_ContentEncoding)
+
+	// check if the request body needs decompression
+	if ENCODING_GZIP == contentEncoding {
+		gzipReader := currentCompressorProvider.AcquireGzipReader()
+		defer currentCompressorProvider.ReleaseGzipReader(gzipReader)
+		gzipReader.Reset(r.Request.Body)
+		r.Request.Body = gzipReader
+	} else if ENCODING_DEFLATE == contentEncoding {
+		zlibReader, err := zlib.NewReader(r.Request.Body)
+		if err != nil {
+			return err
+		}
+		r.Request.Body = zlibReader
+	}
+
+	// lookup the EntityReader, use defaultRequestContentType if needed and provided
+	entityReader, ok := entityAccessRegistry.accessorAt(contentType)
+	if !ok {
+		if len(defaultRequestContentType) != 0 {
+			entityReader, ok = entityAccessRegistry.accessorAt(defaultRequestContentType)
+		}
+		if !ok {
+			return NewError(http.StatusBadRequest, "Unable to unmarshal content of type:"+contentType)
+		}
+	}
+	return entityReader.Read(r, entityPointer)
+}
+
+// SetAttribute adds or replaces the attribute with the given value.
+func (r *Request) SetAttribute(name string, value interface{}) {
+	r.attributes[name] = value
+}
+
+// Attribute returns the value associated to the given name. Returns nil if absent.
+func (r Request) Attribute(name string) interface{} {
+	return r.attributes[name]
+}
+
+// SelectedRoutePath root path + route path that matched the request, e.g. /meetings/{id}/attendees
+func (r Request) SelectedRoutePath() string {
+	return r.selectedRoutePath
+}
diff --git a/metrics-server/vendor/github.com/emicklei/go-restful/response.go b/metrics-server/vendor/github.com/emicklei/go-restful/response.go
new file mode 100644
index 0000000..4d987d1
--- /dev/null
+++ b/metrics-server/vendor/github.com/emicklei/go-restful/response.go
@@ -0,0 +1,250 @@
+package restful
+
+// Copyright 2013 Ernest Micklei. All rights reserved.
+// Use of this source code is governed by a license
+// that can be found in the LICENSE file.
+
+import (
+	"bufio"
+	"errors"
+	"net"
+	"net/http"
+)
+
+// DefaultResponseMimeType is DEPRECATED, use DefaultResponseContentType(mime)
+var DefaultResponseMimeType string
+
+//PrettyPrintResponses controls the indentation feature of XML and JSON serialization
+var PrettyPrintResponses = true
+
+// Response is a wrapper on the actual http ResponseWriter
+// It provides several convenience methods to prepare and write response content.
+type Response struct {
+	http.ResponseWriter
+	requestAccept string        // mime-type what the Http Request says it wants to receive
+	routeProduces []string      // mime-types what the Route says it can produce
+	statusCode    int           // HTTP status code that has been written explicitly (if zero then net/http has written 200)
+	contentLength int           // number of bytes written for the response body
+	prettyPrint   bool          // controls the indentation feature of XML and JSON serialization. It is initialized using var PrettyPrintResponses.
+	err           error         // err property is kept when WriteError is called
+	hijacker      http.Hijacker // if underlying ResponseWriter supports it
+}
+
+// NewResponse creates a new response based on a http ResponseWriter.
+func NewResponse(httpWriter http.ResponseWriter) *Response {
+	hijacker, _ := httpWriter.(http.Hijacker)
+	return &Response{ResponseWriter: httpWriter, routeProduces: []string{}, statusCode: http.StatusOK, prettyPrint: PrettyPrintResponses, hijacker: hijacker}
+}
+
+// DefaultResponseContentType set a default.
+// If Accept header matching fails, fall back to this type.
+// Valid values are restful.MIME_JSON and restful.MIME_XML
+// Example:
+// 	restful.DefaultResponseContentType(restful.MIME_JSON)
+func DefaultResponseContentType(mime string) {
+	DefaultResponseMimeType = mime
+}
+
+// InternalServerError writes the StatusInternalServerError header.
+// DEPRECATED, use WriteErrorString(http.StatusInternalServerError,reason)
+func (r Response) InternalServerError() Response {
+	r.WriteHeader(http.StatusInternalServerError)
+	return r
+}
+
+// Hijack implements the http.Hijacker interface.  This expands
+// the Response to fulfill http.Hijacker if the underlying
+// http.ResponseWriter supports it.
+func (r *Response) Hijack() (net.Conn, *bufio.ReadWriter, error) {
+	if r.hijacker == nil {
+		return nil, nil, errors.New("http.Hijacker not implemented by underlying http.ResponseWriter")
+	}
+	return r.hijacker.Hijack()
+}
+
+// PrettyPrint changes whether this response must produce pretty (line-by-line, indented) JSON or XML output.
+func (r *Response) PrettyPrint(bePretty bool) {
+	r.prettyPrint = bePretty
+}
+
+// AddHeader is a shortcut for .Header().Add(header,value)
+func (r Response) AddHeader(header string, value string) Response {
+	r.Header().Add(header, value)
+	return r
+}
+
+// SetRequestAccepts tells the response what Mime-type(s) the HTTP request said it wants to accept. Exposed for testing.
+func (r *Response) SetRequestAccepts(mime string) {
+	r.requestAccept = mime
+}
+
+// EntityWriter returns the registered EntityWriter that the entity (requested resource)
+// can write according to what the request wants (Accept) and what the Route can produce or what the restful defaults say.
+// If called before WriteEntity and WriteHeader then a false return value can be used to write a 406: Not Acceptable.
+func (r *Response) EntityWriter() (EntityReaderWriter, bool) {
+	sorted := sortedMimes(r.requestAccept)
+	for _, eachAccept := range sorted {
+		for _, eachProduce := range r.routeProduces {
+			if eachProduce == eachAccept.media {
+				if w, ok := entityAccessRegistry.accessorAt(eachAccept.media); ok {
+					return w, true
+				}
+			}
+		}
+		if eachAccept.media == "*/*" {
+			for _, each := range r.routeProduces {
+				if w, ok := entityAccessRegistry.accessorAt(each); ok {
+					return w, true
+				}
+			}
+		}
+	}
+	// if requestAccept is empty
+	writer, ok := entityAccessRegistry.accessorAt(r.requestAccept)
+	if !ok {
+		// if not registered then fallback to the defaults (if set)
+		if DefaultResponseMimeType == MIME_JSON {
+			return entityAccessRegistry.accessorAt(MIME_JSON)
+		}
+		if DefaultResponseMimeType == MIME_XML {
+			return entityAccessRegistry.accessorAt(MIME_XML)
+		}
+		// Fallback to whatever the route says it can produce.
+		// https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
+		for _, each := range r.routeProduces {
+			if w, ok := entityAccessRegistry.accessorAt(each); ok {
+				return w, true
+			}
+		}
+		if trace {
+			traceLogger.Printf("no registered EntityReaderWriter found for %s", r.requestAccept)
+		}
+	}
+	return writer, ok
+}
+
+// WriteEntity calls WriteHeaderAndEntity with Http Status OK (200)
+func (r *Response) WriteEntity(value interface{}) error {
+	return r.WriteHeaderAndEntity(http.StatusOK, value)
+}
+
+// WriteHeaderAndEntity marshals the value using the representation denoted by the Accept Header and the registered EntityWriters.
+// If no Accept header is specified (or */*) then respond with the Content-Type as specified by the first in the Route.Produces.
+// If an Accept header is specified then respond with the Content-Type as specified by the first in the Route.Produces that is matched with the Accept header.
+// If the value is nil then no response is send except for the Http status. You may want to call WriteHeader(http.StatusNotFound) instead.
+// If there is no writer available that can represent the value in the requested MIME type then Http Status NotAcceptable is written.
+// Current implementation ignores any q-parameters in the Accept Header.
+// Returns an error if the value could not be written on the response.
+func (r *Response) WriteHeaderAndEntity(status int, value interface{}) error {
+	writer, ok := r.EntityWriter()
+	if !ok {
+		r.WriteHeader(http.StatusNotAcceptable)
+		return nil
+	}
+	return writer.Write(r, status, value)
+}
+
+// WriteAsXml is a convenience method for writing a value in xml (requires Xml tags on the value)
+// It uses the standard encoding/xml package for marshalling the value ; not using a registered EntityReaderWriter.
+func (r *Response) WriteAsXml(value interface{}) error {
+	return writeXML(r, http.StatusOK, MIME_XML, value)
+}
+
+// WriteHeaderAndXml is a convenience method for writing a status and value in xml (requires Xml tags on the value)
+// It uses the standard encoding/xml package for marshalling the value ; not using a registered EntityReaderWriter.
+func (r *Response) WriteHeaderAndXml(status int, value interface{}) error {
+	return writeXML(r, status, MIME_XML, value)
+}
+
+// WriteAsJson is a convenience method for writing a value in json.
+// It uses the standard encoding/json package for marshalling the value ; not using a registered EntityReaderWriter.
+func (r *Response) WriteAsJson(value interface{}) error {
+	return writeJSON(r, http.StatusOK, MIME_JSON, value)
+}
+
+// WriteJson is a convenience method for writing a value in Json with a given Content-Type.
+// It uses the standard encoding/json package for marshalling the value ; not using a registered EntityReaderWriter.
+func (r *Response) WriteJson(value interface{}, contentType string) error {
+	return writeJSON(r, http.StatusOK, contentType, value)
+}
+
+// WriteHeaderAndJson is a convenience method for writing the status and a value in Json with a given Content-Type.
+// It uses the standard encoding/json package for marshalling the value ; not using a registered EntityReaderWriter.
+func (r *Response) WriteHeaderAndJson(status int, value interface{}, contentType string) error {
+	return writeJSON(r, status, contentType, value)
+}
+
+// WriteError write the http status and the error string on the response.
+func (r *Response) WriteError(httpStatus int, err error) error {
+	r.err = err
+	return r.WriteErrorString(httpStatus, err.Error())
+}
+
+// WriteServiceError is a convenience method for a responding with a status and a ServiceError
+func (r *Response) WriteServiceError(httpStatus int, err ServiceError) error {
+	r.err = err
+	return r.WriteHeaderAndEntity(httpStatus, err)
+}
+
+// WriteErrorString is a convenience method for an error status with the actual error
+func (r *Response) WriteErrorString(httpStatus int, errorReason string) error {
+	if r.err == nil {
+		// if not called from WriteError
+		r.err = errors.New(errorReason)
+	}
+	r.WriteHeader(httpStatus)
+	if _, err := r.Write([]byte(errorReason)); err != nil {
+		return err
+	}
+	return nil
+}
+
+// Flush implements http.Flusher interface, which sends any buffered data to the client.
+func (r *Response) Flush() {
+	if f, ok := r.ResponseWriter.(http.Flusher); ok {
+		f.Flush()
+	} else if trace {
+		traceLogger.Printf("ResponseWriter %v doesn't support Flush", r)
+	}
+}
+
+// WriteHeader is overridden to remember the Status Code that has been written.
+// Changes to the Header of the response have no effect after this.
+func (r *Response) WriteHeader(httpStatus int) {
+	r.statusCode = httpStatus
+	r.ResponseWriter.WriteHeader(httpStatus)
+}
+
+// StatusCode returns the code that has been written using WriteHeader.
+func (r Response) StatusCode() int {
+	if 0 == r.statusCode {
+		// no status code has been written yet; assume OK
+		return http.StatusOK
+	}
+	return r.statusCode
+}
+
+// Write writes the data to the connection as part of an HTTP reply.
+// Write is part of http.ResponseWriter interface.
+func (r *Response) Write(bytes []byte) (int, error) {
+	written, err := r.ResponseWriter.Write(bytes)
+	r.contentLength += written
+	return written, err
+}
+
+// ContentLength returns the number of bytes written for the response content.
+// Note that this value is only correct if all data is written through the Response using its Write* methods.
+// Data written directly using the underlying http.ResponseWriter is not accounted for.
+func (r Response) ContentLength() int {
+	return r.contentLength
+}
+
+// CloseNotify is part of http.CloseNotifier interface
+func (r Response) CloseNotify() <-chan bool {
+	return r.ResponseWriter.(http.CloseNotifier).CloseNotify()
+}
+
+// Error returns the err created by WriteError
+func (r Response) Error() error {
+	return r.err
+}
diff --git a/metrics-server/vendor/github.com/emicklei/go-restful/route.go b/metrics-server/vendor/github.com/emicklei/go-restful/route.go
new file mode 100644
index 0000000..f72bf98
--- /dev/null
+++ b/metrics-server/vendor/github.com/emicklei/go-restful/route.go
@@ -0,0 +1,149 @@
+package restful
+
+// Copyright 2013 Ernest Micklei. All rights reserved.
+// Use of this source code is governed by a license
+// that can be found in the LICENSE file.
+
+import (
+	"net/http"
+	"strings"
+)
+
+// RouteFunction declares the signature of a function that can be bound to a Route.
+type RouteFunction func(*Request, *Response)
+
+// RouteSelectionConditionFunction declares the signature of a function that
+// can be used to add extra conditional logic when selecting whether the route
+// matches the HTTP request.
+type RouteSelectionConditionFunction func(httpRequest *http.Request) bool
+
+// Route binds a HTTP Method,Path,Consumes combination to a RouteFunction.
+type Route struct {
+	Method   string
+	Produces []string
+	Consumes []string
+	Path     string // webservice root path + described path
+	Function RouteFunction
+	Filters  []FilterFunction
+	If       []RouteSelectionConditionFunction
+
+	// cached values for dispatching
+	relativePath string
+	pathParts    []string
+	pathExpr     *pathExpression // cached compilation of relativePath as RegExp
+
+	// documentation
+	Doc                     string
+	Notes                   string
+	Operation               string
+	ParameterDocs           []*Parameter
+	ResponseErrors          map[int]ResponseError
+	ReadSample, WriteSample interface{} // structs that model an example request or response payload
+
+	// Extra information used to store custom information about the route.
+	Metadata map[string]interface{}
+
+	// marks a route as deprecated
+	Deprecated bool
+}
+
+// Initialize for Route
+func (r *Route) postBuild() {
+	r.pathParts = tokenizePath(r.Path)
+}
+
+// Create Request and Response from their http versions
+func (r *Route) wrapRequestResponse(httpWriter http.ResponseWriter, httpRequest *http.Request, pathParams map[string]string) (*Request, *Response) {
+	wrappedRequest := NewRequest(httpRequest)
+	wrappedRequest.pathParameters = pathParams
+	wrappedRequest.selectedRoutePath = r.Path
+	wrappedResponse := NewResponse(httpWriter)
+	wrappedResponse.requestAccept = httpRequest.Header.Get(HEADER_Accept)
+	wrappedResponse.routeProduces = r.Produces
+	return wrappedRequest, wrappedResponse
+}
+
+// dispatchWithFilters call the function after passing through its own filters
+func (r *Route) dispatchWithFilters(wrappedRequest *Request, wrappedResponse *Response) {
+	if len(r.Filters) > 0 {
+		chain := FilterChain{Filters: r.Filters, Target: r.Function}
+		chain.ProcessFilter(wrappedRequest, wrappedResponse)
+	} else {
+		// unfiltered
+		r.Function(wrappedRequest, wrappedResponse)
+	}
+}
+
+// Return whether the mimeType matches to what this Route can produce.
+func (r Route) matchesAccept(mimeTypesWithQuality string) bool {
+	parts := strings.Split(mimeTypesWithQuality, ",")
+	for _, each := range parts {
+		var withoutQuality string
+		if strings.Contains(each, ";") {
+			withoutQuality = strings.Split(each, ";")[0]
+		} else {
+			withoutQuality = each
+		}
+		// trim before compare
+		withoutQuality = strings.Trim(withoutQuality, " ")
+		if withoutQuality == "*/*" {
+			return true
+		}
+		for _, producibleType := range r.Produces {
+			if producibleType == "*/*" || producibleType == withoutQuality {
+				return true
+			}
+		}
+	}
+	return false
+}
+
+// Return whether this Route can consume content with a type specified by mimeTypes (can be empty).
+func (r Route) matchesContentType(mimeTypes string) bool {
+
+	if len(r.Consumes) == 0 {
+		// did not specify what it can consume ;  any media type (“*/*”) is assumed
+		return true
+	}
+
+	if len(mimeTypes) == 0 {
+		// idempotent methods with (most-likely or guaranteed) empty content match missing Content-Type
+		m := r.Method
+		if m == "GET" || m == "HEAD" || m == "OPTIONS" || m == "DELETE" || m == "TRACE" {
+			return true
+		}
+		// proceed with default
+		mimeTypes = MIME_OCTET
+	}
+
+	parts := strings.Split(mimeTypes, ",")
+	for _, each := range parts {
+		var contentType string
+		if strings.Contains(each, ";") {
+			contentType = strings.Split(each, ";")[0]
+		} else {
+			contentType = each
+		}
+		// trim before compare
+		contentType = strings.Trim(contentType, " ")
+		for _, consumeableType := range r.Consumes {
+			if consumeableType == "*/*" || consumeableType == contentType {
+				return true
+			}
+		}
+	}
+	return false
+}
+
+// Tokenize an URL path using the slash separator ; the result does not have empty tokens
+func tokenizePath(path string) []string {
+	if "/" == path {
+		return []string{}
+	}
+	return strings.Split(strings.Trim(path, "/"), "/")
+}
+
+// for debugging
+func (r Route) String() string {
+	return r.Method + " " + r.Path
+}
diff --git a/metrics-server/vendor/github.com/emicklei/go-restful/route_builder.go b/metrics-server/vendor/github.com/emicklei/go-restful/route_builder.go
new file mode 100644
index 0000000..4ebecbd
--- /dev/null
+++ b/metrics-server/vendor/github.com/emicklei/go-restful/route_builder.go
@@ -0,0 +1,321 @@
+package restful
+
+// Copyright 2013 Ernest Micklei. All rights reserved.
+// Use of this source code is governed by a license
+// that can be found in the LICENSE file.
+
+import (
+	"fmt"
+	"os"
+	"reflect"
+	"runtime"
+	"strings"
+	"sync/atomic"
+
+	"github.com/emicklei/go-restful/log"
+)
+
+// RouteBuilder is a helper to construct Routes.
+type RouteBuilder struct {
+	rootPath    string
+	currentPath string
+	produces    []string
+	consumes    []string
+	httpMethod  string        // required
+	function    RouteFunction // required
+	filters     []FilterFunction
+	conditions  []RouteSelectionConditionFunction
+
+	typeNameHandleFunc TypeNameHandleFunction // required
+
+	// documentation
+	doc                     string
+	notes                   string
+	operation               string
+	readSample, writeSample interface{}
+	parameters              []*Parameter
+	errorMap                map[int]ResponseError
+	metadata                map[string]interface{}
+	deprecated              bool
+}
+
+// Do evaluates each argument with the RouteBuilder itself.
+// This allows you to follow DRY principles without breaking the fluent programming style.
+// Example:
+// 		ws.Route(ws.DELETE("/{name}").To(t.deletePerson).Do(Returns200, Returns500))
+//
+//		func Returns500(b *RouteBuilder) {
+//			b.Returns(500, "Internal Server Error", restful.ServiceError{})
+//		}
+func (b *RouteBuilder) Do(oneArgBlocks ...func(*RouteBuilder)) *RouteBuilder {
+	for _, each := range oneArgBlocks {
+		each(b)
+	}
+	return b
+}
+
+// To bind the route to a function.
+// If this route is matched with the incoming Http Request then call this function with the *Request,*Response pair. Required.
+func (b *RouteBuilder) To(function RouteFunction) *RouteBuilder {
+	b.function = function
+	return b
+}
+
+// Method specifies what HTTP method to match. Required.
+func (b *RouteBuilder) Method(method string) *RouteBuilder {
+	b.httpMethod = method
+	return b
+}
+
+// Produces specifies what MIME types can be produced ; the matched one will appear in the Content-Type Http header.
+func (b *RouteBuilder) Produces(mimeTypes ...string) *RouteBuilder {
+	b.produces = mimeTypes
+	return b
+}
+
+// Consumes specifies what MIME types can be consumes ; the Accept Http header must matched any of these
+func (b *RouteBuilder) Consumes(mimeTypes ...string) *RouteBuilder {
+	b.consumes = mimeTypes
+	return b
+}
+
+// Path specifies the relative (w.r.t WebService root path) URL path to match. Default is "/".
+func (b *RouteBuilder) Path(subPath string) *RouteBuilder {
+	b.currentPath = subPath
+	return b
+}
+
+// Doc tells what this route is all about. Optional.
+func (b *RouteBuilder) Doc(documentation string) *RouteBuilder {
+	b.doc = documentation
+	return b
+}
+
+// Notes is a verbose explanation of the operation behavior. Optional.
+func (b *RouteBuilder) Notes(notes string) *RouteBuilder {
+	b.notes = notes
+	return b
+}
+
+// Reads tells what resource type will be read from the request payload. Optional.
+// A parameter of type "body" is added ,required is set to true and the dataType is set to the qualified name of the sample's type.
+func (b *RouteBuilder) Reads(sample interface{}, optionalDescription ...string) *RouteBuilder {
+	fn := b.typeNameHandleFunc
+	if fn == nil {
+		fn = reflectTypeName
+	}
+	typeAsName := fn(sample)
+	description := ""
+	if len(optionalDescription) > 0 {
+		description = optionalDescription[0]
+	}
+	b.readSample = sample
+	bodyParameter := &Parameter{&ParameterData{Name: "body", Description: description}}
+	bodyParameter.beBody()
+	bodyParameter.Required(true)
+	bodyParameter.DataType(typeAsName)
+	b.Param(bodyParameter)
+	return b
+}
+
+// ParameterNamed returns a Parameter already known to the RouteBuilder. Returns nil if not.
+// Use this to modify or extend information for the Parameter (through its Data()).
+func (b RouteBuilder) ParameterNamed(name string) (p *Parameter) {
+	for _, each := range b.parameters {
+		if each.Data().Name == name {
+			return each
+		}
+	}
+	return p
+}
+
+// Writes tells what resource type will be written as the response payload. Optional.
+func (b *RouteBuilder) Writes(sample interface{}) *RouteBuilder {
+	b.writeSample = sample
+	return b
+}
+
+// Param allows you to document the parameters of the Route. It adds a new Parameter (does not check for duplicates).
+func (b *RouteBuilder) Param(parameter *Parameter) *RouteBuilder {
+	if b.parameters == nil {
+		b.parameters = []*Parameter{}
+	}
+	b.parameters = append(b.parameters, parameter)
+	return b
+}
+
+// Operation allows you to document what the actual method/function call is of the Route.
+// Unless called, the operation name is derived from the RouteFunction set using To(..).
+func (b *RouteBuilder) Operation(name string) *RouteBuilder {
+	b.operation = name
+	return b
+}
+
+// ReturnsError is deprecated, use Returns instead.
+func (b *RouteBuilder) ReturnsError(code int, message string, model interface{}) *RouteBuilder {
+	log.Print("ReturnsError is deprecated, use Returns instead.")
+	return b.Returns(code, message, model)
+}
+
+// Returns allows you to document what responses (errors or regular) can be expected.
+// The model parameter is optional ; either pass a struct instance or use nil if not applicable.
+func (b *RouteBuilder) Returns(code int, message string, model interface{}) *RouteBuilder {
+	err := ResponseError{
+		Code:      code,
+		Message:   message,
+		Model:     model,
+		IsDefault: false,
+	}
+	// lazy init because there is no NewRouteBuilder (yet)
+	if b.errorMap == nil {
+		b.errorMap = map[int]ResponseError{}
+	}
+	b.errorMap[code] = err
+	return b
+}
+
+// DefaultReturns is a special Returns call that sets the default of the response ; the code is zero.
+func (b *RouteBuilder) DefaultReturns(message string, model interface{}) *RouteBuilder {
+	b.Returns(0, message, model)
+	// Modify the ResponseError just added/updated
+	re := b.errorMap[0]
+	// errorMap is initialized
+	b.errorMap[0] = ResponseError{
+		Code:      re.Code,
+		Message:   re.Message,
+		Model:     re.Model,
+		IsDefault: true,
+	}
+	return b
+}
+
+// Metadata adds or updates a key=value pair to the metadata map.
+func (b *RouteBuilder) Metadata(key string, value interface{}) *RouteBuilder {
+	if b.metadata == nil {
+		b.metadata = map[string]interface{}{}
+	}
+	b.metadata[key] = value
+	return b
+}
+
+// Deprecate sets the value of deprecated to true.  Deprecated routes have a special UI treatment to warn against use
+func (b *RouteBuilder) Deprecate() *RouteBuilder {
+	b.deprecated = true
+	return b
+}
+
+// ResponseError represents a response; not necessarily an error.
+type ResponseError struct {
+	Code      int
+	Message   string
+	Model     interface{}
+	IsDefault bool
+}
+
+func (b *RouteBuilder) servicePath(path string) *RouteBuilder {
+	b.rootPath = path
+	return b
+}
+
+// Filter appends a FilterFunction to the end of filters for this Route to build.
+func (b *RouteBuilder) Filter(filter FilterFunction) *RouteBuilder {
+	b.filters = append(b.filters, filter)
+	return b
+}
+
+// If sets a condition function that controls matching the Route based on custom logic.
+// The condition function is provided the HTTP request and should return true if the route
+// should be considered.
+//
+// Efficiency note: the condition function is called before checking the method, produces, and
+// consumes criteria, so that the correct HTTP status code can be returned.
+//
+// Lifecycle note: no filter functions have been called prior to calling the condition function,
+// so the condition function should not depend on any context that might be set up by container
+// or route filters.
+func (b *RouteBuilder) If(condition RouteSelectionConditionFunction) *RouteBuilder {
+	b.conditions = append(b.conditions, condition)
+	return b
+}
+
+// If no specific Route path then set to rootPath
+// If no specific Produces then set to rootProduces
+// If no specific Consumes then set to rootConsumes
+func (b *RouteBuilder) copyDefaults(rootProduces, rootConsumes []string) {
+	if len(b.produces) == 0 {
+		b.produces = rootProduces
+	}
+	if len(b.consumes) == 0 {
+		b.consumes = rootConsumes
+	}
+}
+
+// typeNameHandler sets the function that will convert types to strings in the parameter
+// and model definitions.
+func (b *RouteBuilder) typeNameHandler(handler TypeNameHandleFunction) *RouteBuilder {
+	b.typeNameHandleFunc = handler
+	return b
+}
+
+// Build creates a new Route using the specification details collected by the RouteBuilder
+func (b *RouteBuilder) Build() Route {
+	pathExpr, err := newPathExpression(b.currentPath)
+	if err != nil {
+		log.Printf("[restful] Invalid path:%s because:%v", b.currentPath, err)
+		os.Exit(1)
+	}
+	if b.function == nil {
+		log.Printf("[restful] No function specified for route:" + b.currentPath)
+		os.Exit(1)
+	}
+	operationName := b.operation
+	if len(operationName) == 0 && b.function != nil {
+		// extract from definition
+		operationName = nameOfFunction(b.function)
+	}
+	route := Route{
+		Method:         b.httpMethod,
+		Path:           concatPath(b.rootPath, b.currentPath),
+		Produces:       b.produces,
+		Consumes:       b.consumes,
+		Function:       b.function,
+		Filters:        b.filters,
+		If:             b.conditions,
+		relativePath:   b.currentPath,
+		pathExpr:       pathExpr,
+		Doc:            b.doc,
+		Notes:          b.notes,
+		Operation:      operationName,
+		ParameterDocs:  b.parameters,
+		ResponseErrors: b.errorMap,
+		ReadSample:     b.readSample,
+		WriteSample:    b.writeSample,
+		Metadata:       b.metadata,
+		Deprecated:     b.deprecated}
+	route.postBuild()
+	return route
+}
+
+func concatPath(path1, path2 string) string {
+	return strings.TrimRight(path1, "/") + "/" + strings.TrimLeft(path2, "/")
+}
+
+var anonymousFuncCount int32
+
+// nameOfFunction returns the short name of the function f for documentation.
+// It uses a runtime feature for debugging ; its value may change for later Go versions.
+func nameOfFunction(f interface{}) string {
+	fun := runtime.FuncForPC(reflect.ValueOf(f).Pointer())
+	tokenized := strings.Split(fun.Name(), ".")
+	last := tokenized[len(tokenized)-1]
+	last = strings.TrimSuffix(last, ")·fm") // < Go 1.5
+	last = strings.TrimSuffix(last, ")-fm") // Go 1.5
+	last = strings.TrimSuffix(last, "·fm")  // < Go 1.5
+	last = strings.TrimSuffix(last, "-fm")  // Go 1.5
+	if last == "func1" {                    // this could mean conflicts in API docs
+		val := atomic.AddInt32(&anonymousFuncCount, 1)
+		last = "func" + fmt.Sprintf("%d", val)
+		atomic.StoreInt32(&anonymousFuncCount, val)
+	}
+	return last
+}
diff --git a/metrics-server/vendor/github.com/emicklei/go-restful/router.go b/metrics-server/vendor/github.com/emicklei/go-restful/router.go
new file mode 100644
index 0000000..19078af
--- /dev/null
+++ b/metrics-server/vendor/github.com/emicklei/go-restful/router.go
@@ -0,0 +1,20 @@
+package restful
+
+// Copyright 2013 Ernest Micklei. All rights reserved.
+// Use of this source code is governed by a license
+// that can be found in the LICENSE file.
+
+import "net/http"
+
+// A RouteSelector finds the best matching Route given the input HTTP Request
+// RouteSelectors can optionally also implement the PathProcessor interface to also calculate the
+// path parameters after the route has been selected.
+type RouteSelector interface {
+
+	// SelectRoute finds a Route given the input HTTP Request and a list of WebServices.
+	// It returns a selected Route and its containing WebService or an error indicating
+	// a problem.
+	SelectRoute(
+		webServices []*WebService,
+		httpRequest *http.Request) (selectedService *WebService, selected *Route, err error)
+}
diff --git a/metrics-server/vendor/github.com/emicklei/go-restful/service_error.go b/metrics-server/vendor/github.com/emicklei/go-restful/service_error.go
new file mode 100644
index 0000000..62d1108
--- /dev/null
+++ b/metrics-server/vendor/github.com/emicklei/go-restful/service_error.go
@@ -0,0 +1,23 @@
+package restful
+
+// Copyright 2013 Ernest Micklei. All rights reserved.
+// Use of this source code is governed by a license
+// that can be found in the LICENSE file.
+
+import "fmt"
+
+// ServiceError is a transport object to pass information about a non-Http error occurred in a WebService while processing a request.
+type ServiceError struct {
+	Code    int
+	Message string
+}
+
+// NewError returns a ServiceError using the code and reason
+func NewError(code int, message string) ServiceError {
+	return ServiceError{Code: code, Message: message}
+}
+
+// Error returns a text representation of the service error
+func (s ServiceError) Error() string {
+	return fmt.Sprintf("[ServiceError:%v] %v", s.Code, s.Message)
+}
diff --git a/metrics-server/vendor/github.com/emicklei/go-restful/web_service.go b/metrics-server/vendor/github.com/emicklei/go-restful/web_service.go
new file mode 100644
index 0000000..f7e18a5
--- /dev/null
+++ b/metrics-server/vendor/github.com/emicklei/go-restful/web_service.go
@@ -0,0 +1,290 @@
+package restful
+
+import (
+	"errors"
+	"os"
+	"reflect"
+	"sync"
+
+	"github.com/emicklei/go-restful/log"
+)
+
+// Copyright 2013 Ernest Micklei. All rights reserved.
+// Use of this source code is governed by a license
+// that can be found in the LICENSE file.
+
+// WebService holds a collection of Route values that bind a Http Method + URL Path to a function.
+type WebService struct {
+	rootPath       string
+	pathExpr       *pathExpression // cached compilation of rootPath as RegExp
+	routes         []Route
+	produces       []string
+	consumes       []string
+	pathParameters []*Parameter
+	filters        []FilterFunction
+	documentation  string
+	apiVersion     string
+
+	typeNameHandleFunc TypeNameHandleFunction
+
+	dynamicRoutes bool
+
+	// protects 'routes' if dynamic routes are enabled
+	routesLock sync.RWMutex
+}
+
+func (w *WebService) SetDynamicRoutes(enable bool) {
+	w.dynamicRoutes = enable
+}
+
+// TypeNameHandleFunction declares functions that can handle translating the name of a sample object
+// into the restful documentation for the service.
+type TypeNameHandleFunction func(sample interface{}) string
+
+// TypeNameHandler sets the function that will convert types to strings in the parameter
+// and model definitions. If not set, the web service will invoke
+// reflect.TypeOf(object).String().
+func (w *WebService) TypeNameHandler(handler TypeNameHandleFunction) *WebService {
+	w.typeNameHandleFunc = handler
+	return w
+}
+
+// reflectTypeName is the default TypeNameHandleFunction and for a given object
+// returns the name that Go identifies it with (e.g. "string" or "v1.Object") via
+// the reflection API.
+func reflectTypeName(sample interface{}) string {
+	return reflect.TypeOf(sample).String()
+}
+
+// compilePathExpression ensures that the path is compiled into a RegEx for those routers that need it.
+func (w *WebService) compilePathExpression() {
+	compiled, err := newPathExpression(w.rootPath)
+	if err != nil {
+		log.Printf("[restful] invalid path:%s because:%v", w.rootPath, err)
+		os.Exit(1)
+	}
+	w.pathExpr = compiled
+}
+
+// ApiVersion sets the API version for documentation purposes.
+func (w *WebService) ApiVersion(apiVersion string) *WebService {
+	w.apiVersion = apiVersion
+	return w
+}
+
+// Version returns the API version for documentation purposes.
+func (w *WebService) Version() string { return w.apiVersion }
+
+// Path specifies the root URL template path of the WebService.
+// All Routes will be relative to this path.
+func (w *WebService) Path(root string) *WebService {
+	w.rootPath = root
+	if len(w.rootPath) == 0 {
+		w.rootPath = "/"
+	}
+	w.compilePathExpression()
+	return w
+}
+
+// Param adds a PathParameter to document parameters used in the root path.
+func (w *WebService) Param(parameter *Parameter) *WebService {
+	if w.pathParameters == nil {
+		w.pathParameters = []*Parameter{}
+	}
+	w.pathParameters = append(w.pathParameters, parameter)
+	return w
+}
+
+// PathParameter creates a new Parameter of kind Path for documentation purposes.
+// It is initialized as required with string as its DataType.
+func (w *WebService) PathParameter(name, description string) *Parameter {
+	return PathParameter(name, description)
+}
+
+// PathParameter creates a new Parameter of kind Path for documentation purposes.
+// It is initialized as required with string as its DataType.
+func PathParameter(name, description string) *Parameter {
+	p := &Parameter{&ParameterData{Name: name, Description: description, Required: true, DataType: "string"}}
+	p.bePath()
+	return p
+}
+
+// QueryParameter creates a new Parameter of kind Query for documentation purposes.
+// It is initialized as not required with string as its DataType.
+func (w *WebService) QueryParameter(name, description string) *Parameter {
+	return QueryParameter(name, description)
+}
+
+// QueryParameter creates a new Parameter of kind Query for documentation purposes.
+// It is initialized as not required with string as its DataType.
+func QueryParameter(name, description string) *Parameter {
+	p := &Parameter{&ParameterData{Name: name, Description: description, Required: false, DataType: "string", CollectionFormat: CollectionFormatCSV.String()}}
+	p.beQuery()
+	return p
+}
+
+// BodyParameter creates a new Parameter of kind Body for documentation purposes.
+// It is initialized as required without a DataType.
+func (w *WebService) BodyParameter(name, description string) *Parameter {
+	return BodyParameter(name, description)
+}
+
+// BodyParameter creates a new Parameter of kind Body for documentation purposes.
+// It is initialized as required without a DataType.
+func BodyParameter(name, description string) *Parameter {
+	p := &Parameter{&ParameterData{Name: name, Description: description, Required: true}}
+	p.beBody()
+	return p
+}
+
+// HeaderParameter creates a new Parameter of kind (Http) Header for documentation purposes.
+// It is initialized as not required with string as its DataType.
+func (w *WebService) HeaderParameter(name, description string) *Parameter {
+	return HeaderParameter(name, description)
+}
+
+// HeaderParameter creates a new Parameter of kind (Http) Header for documentation purposes.
+// It is initialized as not required with string as its DataType.
+func HeaderParameter(name, description string) *Parameter {
+	p := &Parameter{&ParameterData{Name: name, Description: description, Required: false, DataType: "string"}}
+	p.beHeader()
+	return p
+}
+
+// FormParameter creates a new Parameter of kind Form (using application/x-www-form-urlencoded) for documentation purposes.
+// It is initialized as required with string as its DataType.
+func (w *WebService) FormParameter(name, description string) *Parameter {
+	return FormParameter(name, description)
+}
+
+// FormParameter creates a new Parameter of kind Form (using application/x-www-form-urlencoded) for documentation purposes.
+// It is initialized as required with string as its DataType.
+func FormParameter(name, description string) *Parameter {
+	p := &Parameter{&ParameterData{Name: name, Description: description, Required: false, DataType: "string"}}
+	p.beForm()
+	return p
+}
+
+// Route creates a new Route using the RouteBuilder and add to the ordered list of Routes.
+func (w *WebService) Route(builder *RouteBuilder) *WebService {
+	w.routesLock.Lock()
+	defer w.routesLock.Unlock()
+	builder.copyDefaults(w.produces, w.consumes)
+	w.routes = append(w.routes, builder.Build())
+	return w
+}
+
+// RemoveRoute removes the specified route, looks for something that matches 'path' and 'method'
+func (w *WebService) RemoveRoute(path, method string) error {
+	if !w.dynamicRoutes {
+		return errors.New("dynamic routes are not enabled.")
+	}
+	w.routesLock.Lock()
+	defer w.routesLock.Unlock()
+	newRoutes := make([]Route, (len(w.routes) - 1))
+	current := 0
+	for ix := range w.routes {
+		if w.routes[ix].Method == method && w.routes[ix].Path == path {
+			continue
+		}
+		newRoutes[current] = w.routes[ix]
+		current = current + 1
+	}
+	w.routes = newRoutes
+	return nil
+}
+
+// Method creates a new RouteBuilder and initialize its http method
+func (w *WebService) Method(httpMethod string) *RouteBuilder {
+	return new(RouteBuilder).typeNameHandler(w.typeNameHandleFunc).servicePath(w.rootPath).Method(httpMethod)
+}
+
+// Produces specifies that this WebService can produce one or more MIME types.
+// Http requests must have one of these values set for the Accept header.
+func (w *WebService) Produces(contentTypes ...string) *WebService {
+	w.produces = contentTypes
+	return w
+}
+
+// Consumes specifies that this WebService can consume one or more MIME types.
+// Http requests must have one of these values set for the Content-Type header.
+func (w *WebService) Consumes(accepts ...string) *WebService {
+	w.consumes = accepts
+	return w
+}
+
+// Routes returns the Routes associated with this WebService
+func (w *WebService) Routes() []Route {
+	if !w.dynamicRoutes {
+		return w.routes
+	}
+	// Make a copy of the array to prevent concurrency problems
+	w.routesLock.RLock()
+	defer w.routesLock.RUnlock()
+	result := make([]Route, len(w.routes))
+	for ix := range w.routes {
+		result[ix] = w.routes[ix]
+	}
+	return result
+}
+
+// RootPath returns the RootPath associated with this WebService. Default "/"
+func (w *WebService) RootPath() string {
+	return w.rootPath
+}
+
+// PathParameters return the path parameter names for (shared among its Routes)
+func (w *WebService) PathParameters() []*Parameter {
+	return w.pathParameters
+}
+
+// Filter adds a filter function to the chain of filters applicable to all its Routes
+func (w *WebService) Filter(filter FilterFunction) *WebService {
+	w.filters = append(w.filters, filter)
+	return w
+}
+
+// Doc is used to set the documentation of this service.
+func (w *WebService) Doc(plainText string) *WebService {
+	w.documentation = plainText
+	return w
+}
+
+// Documentation returns it.
+func (w *WebService) Documentation() string {
+	return w.documentation
+}
+
+/*
+	Convenience methods
+*/
+
+// HEAD is a shortcut for .Method("HEAD").Path(subPath)
+func (w *WebService) HEAD(subPath string) *RouteBuilder {
+	return new(RouteBuilder).typeNameHandler(w.typeNameHandleFunc).servicePath(w.rootPath).Method("HEAD").Path(subPath)
+}
+
+// GET is a shortcut for .Method("GET").Path(subPath)
+func (w *WebService) GET(subPath string) *RouteBuilder {
+	return new(RouteBuilder).typeNameHandler(w.typeNameHandleFunc).servicePath(w.rootPath).Method("GET").Path(subPath)
+}
+
+// POST is a shortcut for .Method("POST").Path(subPath)
+func (w *WebService) POST(subPath string) *RouteBuilder {
+	return new(RouteBuilder).typeNameHandler(w.typeNameHandleFunc).servicePath(w.rootPath).Method("POST").Path(subPath)
+}
+
+// PUT is a shortcut for .Method("PUT").Path(subPath)
+func (w *WebService) PUT(subPath string) *RouteBuilder {
+	return new(RouteBuilder).typeNameHandler(w.typeNameHandleFunc).servicePath(w.rootPath).Method("PUT").Path(subPath)
+}
+
+// PATCH is a shortcut for .Method("PATCH").Path(subPath)
+func (w *WebService) PATCH(subPath string) *RouteBuilder {
+	return new(RouteBuilder).typeNameHandler(w.typeNameHandleFunc).servicePath(w.rootPath).Method("PATCH").Path(subPath)
+}
+
+// DELETE is a shortcut for .Method("DELETE").Path(subPath)
+func (w *WebService) DELETE(subPath string) *RouteBuilder {
+	return new(RouteBuilder).typeNameHandler(w.typeNameHandleFunc).servicePath(w.rootPath).Method("DELETE").Path(subPath)
+}
diff --git a/metrics-server/vendor/github.com/emicklei/go-restful/web_service_container.go b/metrics-server/vendor/github.com/emicklei/go-restful/web_service_container.go
new file mode 100644
index 0000000..c9d31b0
--- /dev/null
+++ b/metrics-server/vendor/github.com/emicklei/go-restful/web_service_container.go
@@ -0,0 +1,39 @@
+package restful
+
+// Copyright 2013 Ernest Micklei. All rights reserved.
+// Use of this source code is governed by a license
+// that can be found in the LICENSE file.
+
+import (
+	"net/http"
+)
+
+// DefaultContainer is a restful.Container that uses http.DefaultServeMux
+var DefaultContainer *Container
+
+func init() {
+	DefaultContainer = NewContainer()
+	DefaultContainer.ServeMux = http.DefaultServeMux
+}
+
+// If set the true then panics will not be caught to return HTTP 500.
+// In that case, Route functions are responsible for handling any error situation.
+// Default value is false = recover from panics. This has performance implications.
+// OBSOLETE ; use restful.DefaultContainer.DoNotRecover(true)
+var DoNotRecover = false
+
+// Add registers a new WebService add it to the DefaultContainer.
+func Add(service *WebService) {
+	DefaultContainer.Add(service)
+}
+
+// Filter appends a container FilterFunction from the DefaultContainer.
+// These are called before dispatching a http.Request to a WebService.
+func Filter(filter FilterFunction) {
+	DefaultContainer.Filter(filter)
+}
+
+// RegisteredWebServices returns the collections of WebServices from the DefaultContainer
+func RegisteredWebServices() []*WebService {
+	return DefaultContainer.RegisteredWebServices()
+}