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/k8s.io/kube-openapi/pkg/builder/openapi.go b/metrics-server/vendor/k8s.io/kube-openapi/pkg/builder/openapi.go
new file mode 100644
index 0000000..f48700d
--- /dev/null
+++ b/metrics-server/vendor/k8s.io/kube-openapi/pkg/builder/openapi.go
@@ -0,0 +1,457 @@
+/*
+Copyright 2016 The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package builder
+
+import (
+	"encoding/json"
+	"fmt"
+	"net/http"
+	"reflect"
+	"strings"
+
+	restful "github.com/emicklei/go-restful"
+	"github.com/go-openapi/spec"
+
+	"k8s.io/kube-openapi/pkg/common"
+	"k8s.io/kube-openapi/pkg/util"
+)
+
+const (
+	OpenAPIVersion = "2.0"
+	// TODO: Make this configurable.
+	extensionPrefix = "x-kubernetes-"
+)
+
+type openAPI struct {
+	config       *common.Config
+	swagger      *spec.Swagger
+	protocolList []string
+	definitions  map[string]common.OpenAPIDefinition
+}
+
+// BuildOpenAPISpec builds OpenAPI spec given a list of webservices (containing routes) and common.Config to customize it.
+func BuildOpenAPISpec(webServices []*restful.WebService, config *common.Config) (*spec.Swagger, error) {
+	o := newOpenAPI(config)
+	err := o.buildPaths(webServices)
+	if err != nil {
+		return nil, err
+	}
+	return o.finalizeSwagger()
+}
+
+// BuildOpenAPIDefinitionsForResource builds a partial OpenAPI spec given a sample object and common.Config to customize it.
+func BuildOpenAPIDefinitionsForResource(model interface{}, config *common.Config) (*spec.Definitions, error) {
+	o := newOpenAPI(config)
+	// We can discard the return value of toSchema because all we care about is the side effect of calling it.
+	// All the models created for this resource get added to o.swagger.Definitions
+	_, err := o.toSchema(getCanonicalTypeName(model))
+	if err != nil {
+		return nil, err
+	}
+	swagger, err := o.finalizeSwagger()
+	if err != nil {
+		return nil, err
+	}
+	return &swagger.Definitions, nil
+}
+
+// BuildOpenAPIDefinitionsForResources returns the OpenAPI spec which includes the definitions for the
+// passed type names.
+func BuildOpenAPIDefinitionsForResources(config *common.Config, names ...string) (*spec.Swagger, error) {
+	o := newOpenAPI(config)
+	// We can discard the return value of toSchema because all we care about is the side effect of calling it.
+	// All the models created for this resource get added to o.swagger.Definitions
+	for _, name := range names {
+		_, err := o.toSchema(name)
+		if err != nil {
+			return nil, err
+		}
+	}
+	return o.finalizeSwagger()
+}
+
+// newOpenAPI sets up the openAPI object so we can build the spec.
+func newOpenAPI(config *common.Config) openAPI {
+	o := openAPI{
+		config: config,
+		swagger: &spec.Swagger{
+			SwaggerProps: spec.SwaggerProps{
+				Swagger:     OpenAPIVersion,
+				Definitions: spec.Definitions{},
+				Paths:       &spec.Paths{Paths: map[string]spec.PathItem{}},
+				Info:        config.Info,
+			},
+		},
+	}
+	if o.config.GetOperationIDAndTags == nil {
+		o.config.GetOperationIDAndTags = func(r *restful.Route) (string, []string, error) {
+			return r.Operation, nil, nil
+		}
+	}
+	if o.config.GetDefinitionName == nil {
+		o.config.GetDefinitionName = func(name string) (string, spec.Extensions) {
+			return name[strings.LastIndex(name, "/")+1:], nil
+		}
+	}
+	o.definitions = o.config.GetDefinitions(func(name string) spec.Ref {
+		defName, _ := o.config.GetDefinitionName(name)
+		return spec.MustCreateRef("#/definitions/" + common.EscapeJsonPointer(defName))
+	})
+	if o.config.CommonResponses == nil {
+		o.config.CommonResponses = map[int]spec.Response{}
+	}
+	return o
+}
+
+// finalizeSwagger is called after the spec is built and returns the final spec.
+// NOTE: finalizeSwagger also make changes to the final spec, as specified in the config.
+func (o *openAPI) finalizeSwagger() (*spec.Swagger, error) {
+	if o.config.SecurityDefinitions != nil {
+		o.swagger.SecurityDefinitions = *o.config.SecurityDefinitions
+		o.swagger.Security = o.config.DefaultSecurity
+	}
+	if o.config.PostProcessSpec != nil {
+		var err error
+		o.swagger, err = o.config.PostProcessSpec(o.swagger)
+		if err != nil {
+			return nil, err
+		}
+	}
+
+	return o.swagger, nil
+}
+
+func getCanonicalTypeName(model interface{}) string {
+	t := reflect.TypeOf(model)
+	if t.Kind() == reflect.Ptr {
+		t = t.Elem()
+	}
+	if t.PkgPath() == "" {
+		return t.Name()
+	}
+	path := t.PkgPath()
+	if strings.Contains(path, "/vendor/") {
+		path = path[strings.Index(path, "/vendor/")+len("/vendor/"):]
+	}
+	return path + "." + t.Name()
+}
+
+func (o *openAPI) buildDefinitionRecursively(name string) error {
+	uniqueName, extensions := o.config.GetDefinitionName(name)
+	if _, ok := o.swagger.Definitions[uniqueName]; ok {
+		return nil
+	}
+	if item, ok := o.definitions[name]; ok {
+		schema := spec.Schema{
+			VendorExtensible:   item.Schema.VendorExtensible,
+			SchemaProps:        item.Schema.SchemaProps,
+			SwaggerSchemaProps: item.Schema.SwaggerSchemaProps,
+		}
+		if extensions != nil {
+			if schema.Extensions == nil {
+				schema.Extensions = spec.Extensions{}
+			}
+			for k, v := range extensions {
+				schema.Extensions[k] = v
+			}
+		}
+		o.swagger.Definitions[uniqueName] = schema
+		for _, v := range item.Dependencies {
+			if err := o.buildDefinitionRecursively(v); err != nil {
+				return err
+			}
+		}
+	} else {
+		return fmt.Errorf("cannot find model definition for %v. If you added a new type, you may need to add +k8s:openapi-gen=true to the package or type and run code-gen again", name)
+	}
+	return nil
+}
+
+// buildDefinitionForType build a definition for a given type and return a referable name to its definition.
+// This is the main function that keep track of definitions used in this spec and is depend on code generated
+// by k8s.io/kubernetes/cmd/libs/go2idl/openapi-gen.
+func (o *openAPI) buildDefinitionForType(name string) (string, error) {
+	if err := o.buildDefinitionRecursively(name); err != nil {
+		return "", err
+	}
+	defName, _ := o.config.GetDefinitionName(name)
+	return "#/definitions/" + common.EscapeJsonPointer(defName), nil
+}
+
+// buildPaths builds OpenAPI paths using go-restful's web services.
+func (o *openAPI) buildPaths(webServices []*restful.WebService) error {
+	pathsToIgnore := util.NewTrie(o.config.IgnorePrefixes)
+	duplicateOpId := make(map[string]string)
+	for _, w := range webServices {
+		rootPath := w.RootPath()
+		if pathsToIgnore.HasPrefix(rootPath) {
+			continue
+		}
+		commonParams, err := o.buildParameters(w.PathParameters())
+		if err != nil {
+			return err
+		}
+		for path, routes := range groupRoutesByPath(w.Routes()) {
+			// go-swagger has special variable definition {$NAME:*} that can only be
+			// used at the end of the path and it is not recognized by OpenAPI.
+			if strings.HasSuffix(path, ":*}") {
+				path = path[:len(path)-3] + "}"
+			}
+			if pathsToIgnore.HasPrefix(path) {
+				continue
+			}
+			// Aggregating common parameters make API spec (and generated clients) simpler
+			inPathCommonParamsMap, err := o.findCommonParameters(routes)
+			if err != nil {
+				return err
+			}
+			pathItem, exists := o.swagger.Paths.Paths[path]
+			if exists {
+				return fmt.Errorf("duplicate webservice route has been found for path: %v", path)
+			}
+			pathItem = spec.PathItem{
+				PathItemProps: spec.PathItemProps{
+					Parameters: make([]spec.Parameter, 0),
+				},
+			}
+			// add web services's parameters as well as any parameters appears in all ops, as common parameters
+			pathItem.Parameters = append(pathItem.Parameters, commonParams...)
+			for _, p := range inPathCommonParamsMap {
+				pathItem.Parameters = append(pathItem.Parameters, p)
+			}
+			sortParameters(pathItem.Parameters)
+			for _, route := range routes {
+				op, err := o.buildOperations(route, inPathCommonParamsMap)
+				sortParameters(op.Parameters)
+				if err != nil {
+					return err
+				}
+				dpath, exists := duplicateOpId[op.ID]
+				if exists {
+					return fmt.Errorf("duplicate Operation ID %v for path %v and %v", op.ID, dpath, path)
+				} else {
+					duplicateOpId[op.ID] = path
+				}
+				switch strings.ToUpper(route.Method) {
+				case "GET":
+					pathItem.Get = op
+				case "POST":
+					pathItem.Post = op
+				case "HEAD":
+					pathItem.Head = op
+				case "PUT":
+					pathItem.Put = op
+				case "DELETE":
+					pathItem.Delete = op
+				case "OPTIONS":
+					pathItem.Options = op
+				case "PATCH":
+					pathItem.Patch = op
+				}
+			}
+			o.swagger.Paths.Paths[path] = pathItem
+		}
+	}
+	return nil
+}
+
+// buildOperations builds operations for each webservice path
+func (o *openAPI) buildOperations(route restful.Route, inPathCommonParamsMap map[interface{}]spec.Parameter) (ret *spec.Operation, err error) {
+	ret = &spec.Operation{
+		OperationProps: spec.OperationProps{
+			Description: route.Doc,
+			Consumes:    route.Consumes,
+			Produces:    route.Produces,
+			Schemes:     o.config.ProtocolList,
+			Responses: &spec.Responses{
+				ResponsesProps: spec.ResponsesProps{
+					StatusCodeResponses: make(map[int]spec.Response),
+				},
+			},
+		},
+	}
+	for k, v := range route.Metadata {
+		if strings.HasPrefix(k, extensionPrefix) {
+			if ret.Extensions == nil {
+				ret.Extensions = spec.Extensions{}
+			}
+			ret.Extensions.Add(k, v)
+		}
+	}
+	if ret.ID, ret.Tags, err = o.config.GetOperationIDAndTags(&route); err != nil {
+		return ret, err
+	}
+
+	// Build responses
+	for _, resp := range route.ResponseErrors {
+		ret.Responses.StatusCodeResponses[resp.Code], err = o.buildResponse(resp.Model, resp.Message)
+		if err != nil {
+			return ret, err
+		}
+	}
+	// If there is no response but a write sample, assume that write sample is an http.StatusOK response.
+	if len(ret.Responses.StatusCodeResponses) == 0 && route.WriteSample != nil {
+		ret.Responses.StatusCodeResponses[http.StatusOK], err = o.buildResponse(route.WriteSample, "OK")
+		if err != nil {
+			return ret, err
+		}
+	}
+	for code, resp := range o.config.CommonResponses {
+		if _, exists := ret.Responses.StatusCodeResponses[code]; !exists {
+			ret.Responses.StatusCodeResponses[code] = resp
+		}
+	}
+	// If there is still no response, use default response provided.
+	if len(ret.Responses.StatusCodeResponses) == 0 {
+		ret.Responses.Default = o.config.DefaultResponse
+	}
+
+	// Build non-common Parameters
+	ret.Parameters = make([]spec.Parameter, 0)
+	for _, param := range route.ParameterDocs {
+		if _, isCommon := inPathCommonParamsMap[mapKeyFromParam(param)]; !isCommon {
+			openAPIParam, err := o.buildParameter(param.Data(), route.ReadSample)
+			if err != nil {
+				return ret, err
+			}
+			ret.Parameters = append(ret.Parameters, openAPIParam)
+		}
+	}
+	return ret, nil
+}
+
+func (o *openAPI) buildResponse(model interface{}, description string) (spec.Response, error) {
+	schema, err := o.toSchema(getCanonicalTypeName(model))
+	if err != nil {
+		return spec.Response{}, err
+	}
+	return spec.Response{
+		ResponseProps: spec.ResponseProps{
+			Description: description,
+			Schema:      schema,
+		},
+	}, nil
+}
+
+func (o *openAPI) findCommonParameters(routes []restful.Route) (map[interface{}]spec.Parameter, error) {
+	commonParamsMap := make(map[interface{}]spec.Parameter, 0)
+	paramOpsCountByName := make(map[interface{}]int, 0)
+	paramNameKindToDataMap := make(map[interface{}]restful.ParameterData, 0)
+	for _, route := range routes {
+		routeParamDuplicateMap := make(map[interface{}]bool)
+		s := ""
+		for _, param := range route.ParameterDocs {
+			m, _ := json.Marshal(param.Data())
+			s += string(m) + "\n"
+			key := mapKeyFromParam(param)
+			if routeParamDuplicateMap[key] {
+				msg, _ := json.Marshal(route.ParameterDocs)
+				return commonParamsMap, fmt.Errorf("duplicate parameter %v for route %v, %v", param.Data().Name, string(msg), s)
+			}
+			routeParamDuplicateMap[key] = true
+			paramOpsCountByName[key]++
+			paramNameKindToDataMap[key] = param.Data()
+		}
+	}
+	for key, count := range paramOpsCountByName {
+		paramData := paramNameKindToDataMap[key]
+		if count == len(routes) && paramData.Kind != restful.BodyParameterKind {
+			openAPIParam, err := o.buildParameter(paramData, nil)
+			if err != nil {
+				return commonParamsMap, err
+			}
+			commonParamsMap[key] = openAPIParam
+		}
+	}
+	return commonParamsMap, nil
+}
+
+func (o *openAPI) toSchema(name string) (_ *spec.Schema, err error) {
+	if openAPIType, openAPIFormat := common.GetOpenAPITypeFormat(name); openAPIType != "" {
+		return &spec.Schema{
+			SchemaProps: spec.SchemaProps{
+				Type:   []string{openAPIType},
+				Format: openAPIFormat,
+			},
+		}, nil
+	} else {
+		ref, err := o.buildDefinitionForType(name)
+		if err != nil {
+			return nil, err
+		}
+		return &spec.Schema{
+			SchemaProps: spec.SchemaProps{
+				Ref: spec.MustCreateRef(ref),
+			},
+		}, nil
+	}
+}
+
+func (o *openAPI) buildParameter(restParam restful.ParameterData, bodySample interface{}) (ret spec.Parameter, err error) {
+	ret = spec.Parameter{
+		ParamProps: spec.ParamProps{
+			Name:        restParam.Name,
+			Description: restParam.Description,
+			Required:    restParam.Required,
+		},
+	}
+	switch restParam.Kind {
+	case restful.BodyParameterKind:
+		if bodySample != nil {
+			ret.In = "body"
+			ret.Schema, err = o.toSchema(getCanonicalTypeName(bodySample))
+			return ret, err
+		} else {
+			// There is not enough information in the body parameter to build the definition.
+			// Body parameter has a data type that is a short name but we need full package name
+			// of the type to create a definition.
+			return ret, fmt.Errorf("restful body parameters are not supported: %v", restParam.DataType)
+		}
+	case restful.PathParameterKind:
+		ret.In = "path"
+		if !restParam.Required {
+			return ret, fmt.Errorf("path parameters should be marked at required for parameter %v", restParam)
+		}
+	case restful.QueryParameterKind:
+		ret.In = "query"
+	case restful.HeaderParameterKind:
+		ret.In = "header"
+	case restful.FormParameterKind:
+		ret.In = "formData"
+	default:
+		return ret, fmt.Errorf("unknown restful operation kind : %v", restParam.Kind)
+	}
+	openAPIType, openAPIFormat := common.GetOpenAPITypeFormat(restParam.DataType)
+	if openAPIType == "" {
+		return ret, fmt.Errorf("non-body Restful parameter type should be a simple type, but got : %v", restParam.DataType)
+	}
+	ret.Type = openAPIType
+	ret.Format = openAPIFormat
+	ret.UniqueItems = !restParam.AllowMultiple
+	return ret, nil
+}
+
+func (o *openAPI) buildParameters(restParam []*restful.Parameter) (ret []spec.Parameter, err error) {
+	ret = make([]spec.Parameter, len(restParam))
+	for i, v := range restParam {
+		ret[i], err = o.buildParameter(v.Data(), nil)
+		if err != nil {
+			return ret, err
+		}
+	}
+	return ret, nil
+}