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/LICENSE b/metrics-server/vendor/k8s.io/kube-openapi/LICENSE
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/metrics-server/vendor/k8s.io/kube-openapi/LICENSE
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ 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.
diff --git a/metrics-server/vendor/k8s.io/kube-openapi/cmd/openapi-gen/args/args.go b/metrics-server/vendor/k8s.io/kube-openapi/cmd/openapi-gen/args/args.go
new file mode 100644
index 0000000..f555bdd
--- /dev/null
+++ b/metrics-server/vendor/k8s.io/kube-openapi/cmd/openapi-gen/args/args.go
@@ -0,0 +1,73 @@
+/*
+Copyright 2018 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 args
+
+import (
+ "fmt"
+
+ "github.com/spf13/pflag"
+ "k8s.io/gengo/args"
+)
+
+// CustomArgs is used by the gengo framework to pass args specific to this generator.
+type CustomArgs struct {
+ // ReportFilename is added to CustomArgs for specifying name of report file used
+ // by API linter. If specified, API rule violations will be printed to report file.
+ // Otherwise default value "-" will be used which indicates stdout.
+ ReportFilename string
+}
+
+// NewDefaults returns default arguments for the generator. Returning the arguments instead
+// of using default flag parsing allows registering custom arguments afterwards
+func NewDefaults() (*args.GeneratorArgs, *CustomArgs) {
+ // Default() sets a couple of flag default values for example the boilerplate.
+ // WithoutDefaultFlagParsing() disables implicit addition of command line flags and parsing,
+ // which allows registering custom arguments afterwards
+ genericArgs := args.Default().WithoutDefaultFlagParsing()
+ customArgs := &CustomArgs{}
+ genericArgs.CustomArgs = customArgs
+
+ // Default value for report filename is "-", which stands for stdout
+ customArgs.ReportFilename = "-"
+ // Default value for output file base name
+ genericArgs.OutputFileBaseName = "openapi_generated"
+
+ return genericArgs, customArgs
+}
+
+// AddFlags add the generator flags to the flag set.
+func (c *CustomArgs) AddFlags(fs *pflag.FlagSet) {
+ fs.StringVarP(&c.ReportFilename, "report-filename", "r", c.ReportFilename, "Name of report file used by API linter to print API violations. Default \"-\" stands for standard output. NOTE that if valid filename other than \"-\" is specified, API linter won't return error on detected API violations. This allows further check of existing API violations without stopping the OpenAPI generation toolchain.")
+}
+
+// Validate checks the given arguments.
+func Validate(genericArgs *args.GeneratorArgs) error {
+ c, ok := genericArgs.CustomArgs.(*CustomArgs)
+ if !ok {
+ return fmt.Errorf("input arguments don't contain valid custom arguments")
+ }
+ if len(c.ReportFilename) == 0 {
+ return fmt.Errorf("report filename cannot be empty. specify a valid filename or use \"-\" for stdout")
+ }
+ if len(genericArgs.OutputFileBaseName) == 0 {
+ return fmt.Errorf("output file base name cannot be empty")
+ }
+ if len(genericArgs.OutputPackagePath) == 0 {
+ return fmt.Errorf("output package cannot be empty")
+ }
+ return nil
+}
diff --git a/metrics-server/vendor/k8s.io/kube-openapi/cmd/openapi-gen/openapi-gen.go b/metrics-server/vendor/k8s.io/kube-openapi/cmd/openapi-gen/openapi-gen.go
new file mode 100644
index 0000000..0f7563b
--- /dev/null
+++ b/metrics-server/vendor/k8s.io/kube-openapi/cmd/openapi-gen/openapi-gen.go
@@ -0,0 +1,55 @@
+/*
+Copyright 2018 The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+// This package generates openAPI definition file to be used in open API spec generation on API servers. To generate
+// definition for a specific type or package add "+k8s:openapi-gen=true" tag to the type/package comment lines. To
+// exclude a type from a tagged package, add "+k8s:openapi-gen=false" tag to the type comment lines.
+
+package main
+
+import (
+ "flag"
+ "log"
+
+ generatorargs "k8s.io/kube-openapi/cmd/openapi-gen/args"
+ "k8s.io/kube-openapi/pkg/generators"
+
+ "github.com/spf13/pflag"
+)
+
+func main() {
+ genericArgs, customArgs := generatorargs.NewDefaults()
+
+ genericArgs.AddFlags(pflag.CommandLine)
+ customArgs.AddFlags(pflag.CommandLine)
+ flag.Set("logtostderr", "true")
+ pflag.CommandLine.AddGoFlagSet(flag.CommandLine)
+ pflag.Parse()
+
+ if err := generatorargs.Validate(genericArgs); err != nil {
+ log.Fatalf("Arguments validation error: %v", err)
+ }
+
+ // Generates the code for the OpenAPIDefinitions.
+ if err := genericArgs.Execute(
+ generators.NameSystems(),
+ generators.DefaultNameSystem(),
+ generators.Packages,
+ ); err != nil {
+ log.Fatalf("OpenAPI code generation error: %v", err)
+ }
+ log.Println("Code for OpenAPI definitions generated")
+}
diff --git a/metrics-server/vendor/k8s.io/kube-openapi/pkg/builder/doc.go b/metrics-server/vendor/k8s.io/kube-openapi/pkg/builder/doc.go
new file mode 100644
index 0000000..c310906
--- /dev/null
+++ b/metrics-server/vendor/k8s.io/kube-openapi/pkg/builder/doc.go
@@ -0,0 +1,20 @@
+/*
+Copyright 2016 The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+// Package builder contains code to generate OpenAPI discovery spec (which
+// initial version of it also known as Swagger 2.0).
+// For more details: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md
+package builder
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
+}
diff --git a/metrics-server/vendor/k8s.io/kube-openapi/pkg/builder/util.go b/metrics-server/vendor/k8s.io/kube-openapi/pkg/builder/util.go
new file mode 100644
index 0000000..5e9a56a
--- /dev/null
+++ b/metrics-server/vendor/k8s.io/kube-openapi/pkg/builder/util.go
@@ -0,0 +1,61 @@
+/*
+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 (
+ "sort"
+
+ "github.com/emicklei/go-restful"
+ "github.com/go-openapi/spec"
+)
+
+type parameters []spec.Parameter
+
+func (s parameters) Len() int { return len(s) }
+func (s parameters) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
+
+// byNameIn used in sorting parameters by Name and In fields.
+type byNameIn struct {
+ parameters
+}
+
+func (s byNameIn) Less(i, j int) bool {
+ return s.parameters[i].Name < s.parameters[j].Name || (s.parameters[i].Name == s.parameters[j].Name && s.parameters[i].In < s.parameters[j].In)
+}
+
+// SortParameters sorts parameters by Name and In fields.
+func sortParameters(p []spec.Parameter) {
+ sort.Sort(byNameIn{p})
+}
+
+func groupRoutesByPath(routes []restful.Route) map[string][]restful.Route {
+ pathToRoutes := make(map[string][]restful.Route)
+ for _, r := range routes {
+ pathToRoutes[r.Path] = append(pathToRoutes[r.Path], r)
+ }
+ return pathToRoutes
+}
+
+func mapKeyFromParam(param *restful.Parameter) interface{} {
+ return struct {
+ Name string
+ Kind int
+ }{
+ Name: param.Data().Name,
+ Kind: param.Data().Kind,
+ }
+}
diff --git a/metrics-server/vendor/k8s.io/kube-openapi/pkg/common/common.go b/metrics-server/vendor/k8s.io/kube-openapi/pkg/common/common.go
new file mode 100644
index 0000000..0d23587
--- /dev/null
+++ b/metrics-server/vendor/k8s.io/kube-openapi/pkg/common/common.go
@@ -0,0 +1,168 @@
+/*
+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 common
+
+import (
+ "net/http"
+ "strings"
+
+ "github.com/emicklei/go-restful"
+ "github.com/go-openapi/spec"
+)
+
+// OpenAPIDefinition describes single type. Normally these definitions are auto-generated using gen-openapi.
+type OpenAPIDefinition struct {
+ Schema spec.Schema
+ Dependencies []string
+}
+
+type ReferenceCallback func(path string) spec.Ref
+
+// GetOpenAPIDefinitions is collection of all definitions.
+type GetOpenAPIDefinitions func(ReferenceCallback) map[string]OpenAPIDefinition
+
+// OpenAPIDefinitionGetter gets openAPI definitions for a given type. If a type implements this interface,
+// the definition returned by it will be used, otherwise the auto-generated definitions will be used. See
+// GetOpenAPITypeFormat for more information about trade-offs of using this interface or GetOpenAPITypeFormat method when
+// possible.
+type OpenAPIDefinitionGetter interface {
+ OpenAPIDefinition() *OpenAPIDefinition
+}
+
+type PathHandler interface {
+ Handle(path string, handler http.Handler)
+}
+
+// Config is set of configuration for openAPI spec generation.
+type Config struct {
+ // List of supported protocols such as https, http, etc.
+ ProtocolList []string
+
+ // Info is general information about the API.
+ Info *spec.Info
+
+ // DefaultResponse will be used if an operation does not have any responses listed. It
+ // will show up as ... "responses" : {"default" : $DefaultResponse} in the spec.
+ DefaultResponse *spec.Response
+
+ // CommonResponses will be added as a response to all operation specs. This is a good place to add common
+ // responses such as authorization failed.
+ CommonResponses map[int]spec.Response
+
+ // List of webservice's path prefixes to ignore
+ IgnorePrefixes []string
+
+ // OpenAPIDefinitions should provide definition for all models used by routes. Failure to provide this map
+ // or any of the models will result in spec generation failure.
+ GetDefinitions GetOpenAPIDefinitions
+
+ // GetOperationIDAndTags returns operation id and tags for a restful route. It is an optional function to customize operation IDs.
+ GetOperationIDAndTags func(r *restful.Route) (string, []string, error)
+
+ // GetDefinitionName returns a friendly name for a definition base on the serving path. parameter `name` is the full name of the definition.
+ // It is an optional function to customize model names.
+ GetDefinitionName func(name string) (string, spec.Extensions)
+
+ // PostProcessSpec runs after the spec is ready to serve. It allows a final modification to the spec before serving.
+ PostProcessSpec func(*spec.Swagger) (*spec.Swagger, error)
+
+ // SecurityDefinitions is list of all security definitions for OpenAPI service. If this is not nil, the user of config
+ // is responsible to provide DefaultSecurity and (maybe) add unauthorized response to CommonResponses.
+ SecurityDefinitions *spec.SecurityDefinitions
+
+ // DefaultSecurity for all operations. This will pass as spec.SwaggerProps.Security to OpenAPI.
+ // For most cases, this will be list of acceptable definitions in SecurityDefinitions.
+ DefaultSecurity []map[string][]string
+}
+
+var schemaTypeFormatMap = map[string][]string{
+ "uint": {"integer", "int32"},
+ "uint8": {"integer", "byte"},
+ "uint16": {"integer", "int32"},
+ "uint32": {"integer", "int64"},
+ "uint64": {"integer", "int64"},
+ "int": {"integer", "int32"},
+ "int8": {"integer", "byte"},
+ "int16": {"integer", "int32"},
+ "int32": {"integer", "int32"},
+ "int64": {"integer", "int64"},
+ "byte": {"integer", "byte"},
+ "float64": {"number", "double"},
+ "float32": {"number", "float"},
+ "bool": {"boolean", ""},
+ "time.Time": {"string", "date-time"},
+ "string": {"string", ""},
+ "integer": {"integer", ""},
+ "number": {"number", ""},
+ "boolean": {"boolean", ""},
+ "[]byte": {"string", "byte"}, // base64 encoded characters
+ "interface{}": {"object", ""},
+}
+
+// This function is a reference for converting go (or any custom type) to a simple open API type,format pair. There are
+// two ways to customize spec for a type. If you add it here, a type will be converted to a simple type and the type
+// comment (the comment that is added before type definition) will be lost. The spec will still have the property
+// comment. The second way is to implement OpenAPIDefinitionGetter interface. That function can customize the spec (so
+// the spec does not need to be simple type,format) or can even return a simple type,format (e.g. IntOrString). For simple
+// type formats, the benefit of adding OpenAPIDefinitionGetter interface is to keep both type and property documentation.
+// Example:
+// type Sample struct {
+// ...
+// // port of the server
+// port IntOrString
+// ...
+// }
+// // IntOrString documentation...
+// type IntOrString { ... }
+//
+// Adding IntOrString to this function:
+// "port" : {
+// format: "string",
+// type: "int-or-string",
+// Description: "port of the server"
+// }
+//
+// Implement OpenAPIDefinitionGetter for IntOrString:
+//
+// "port" : {
+// $Ref: "#/definitions/IntOrString"
+// Description: "port of the server"
+// }
+// ...
+// definitions:
+// {
+// "IntOrString": {
+// format: "string",
+// type: "int-or-string",
+// Description: "IntOrString documentation..." // new
+// }
+// }
+//
+func GetOpenAPITypeFormat(typeName string) (string, string) {
+ mapped, ok := schemaTypeFormatMap[typeName]
+ if !ok {
+ return "", ""
+ }
+ return mapped[0], mapped[1]
+}
+
+func EscapeJsonPointer(p string) string {
+ // Escaping reference name using rfc6901
+ p = strings.Replace(p, "~", "~0", -1)
+ p = strings.Replace(p, "/", "~1", -1)
+ return p
+}
diff --git a/metrics-server/vendor/k8s.io/kube-openapi/pkg/common/doc.go b/metrics-server/vendor/k8s.io/kube-openapi/pkg/common/doc.go
new file mode 100644
index 0000000..2ba6d24
--- /dev/null
+++ b/metrics-server/vendor/k8s.io/kube-openapi/pkg/common/doc.go
@@ -0,0 +1,19 @@
+/*
+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 common holds shared code and types between open API code
+// generator and spec generator.
+package common
diff --git a/metrics-server/vendor/k8s.io/kube-openapi/pkg/generators/README b/metrics-server/vendor/k8s.io/kube-openapi/pkg/generators/README
new file mode 100644
index 0000000..feb19b4
--- /dev/null
+++ b/metrics-server/vendor/k8s.io/kube-openapi/pkg/generators/README
@@ -0,0 +1,46 @@
+# Generate OpenAPI definitions
+
+- To generate definition for a specific type or package add "+k8s:openapi-gen=true" tag to the type/package comment lines.
+- To exclude a type or a member from a tagged package/type, add "+k8s:openapi-gen=false" tag to the comment lines.
+
+# OpenAPI Extensions
+OpenAPI spec can have extensions on types. To define one or more extensions on a type or its member
+add `+k8s:openapi-gen=x-kubernetes-$NAME:`$VALUE`` to the comment lines before type/member. A type/member can
+have multiple extensions. The rest of the line in the comment will be used as $VALUE so there is no need to
+escape or quote the value string. Extensions can be used to pass more information to client generators or
+documentation generators. For example a type might have a friendly name to be displayed in documentation or
+being used in a client's fluent interface.
+
+# Custom OpenAPI type definitions
+
+Custom types which otherwise don't map directly to OpenAPI can override their
+OpenAPI definition by implementing a function named "OpenAPIDefinition" with
+the following signature:
+
+ import openapi "k8s.io/kube-openapi/pkg/common"
+
+ // ...
+
+ type Time struct {
+ time.Time
+ }
+
+ func (_ Time) OpenAPIDefinition() openapi.OpenAPIDefinition {
+ return openapi.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"string"},
+ Format: "date-time",
+ },
+ },
+ }
+ }
+
+Alternatively, the type can avoid the "openapi" import by defining the following
+methods. The following example produces the same OpenAPI definition as the
+example above:
+
+ func (_ Time) OpenAPISchemaType() []string { return []string{"string"} }
+ func (_ Time) OpenAPISchemaFormat() string { return "date-time" }
+
+TODO(mehdy): Make k8s:openapi-gen a parameter to the generator now that OpenAPI has its own repo.
diff --git a/metrics-server/vendor/k8s.io/kube-openapi/pkg/generators/api_linter.go b/metrics-server/vendor/k8s.io/kube-openapi/pkg/generators/api_linter.go
new file mode 100644
index 0000000..9270d26
--- /dev/null
+++ b/metrics-server/vendor/k8s.io/kube-openapi/pkg/generators/api_linter.go
@@ -0,0 +1,100 @@
+/*
+Copyright 2018 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 generators
+
+import (
+ "fmt"
+ "io"
+
+ "k8s.io/kube-openapi/pkg/generators/rules"
+
+ "github.com/golang/glog"
+ "k8s.io/gengo/types"
+)
+
+// apiLinter is the framework hosting mutliple API rules and recording API rule
+// violations
+type apiLinter struct {
+ // API rules that implement APIRule interface and output API rule violations
+ rules []APIRule
+ violations []apiViolation
+}
+
+// newAPILinter creates an apiLinter object with API rules in package rules. Please
+// add APIRule here when new API rule is implemented.
+func newAPILinter() *apiLinter {
+ return &apiLinter{
+ rules: []APIRule{
+ &rules.NamesMatch{},
+ },
+ }
+}
+
+// apiViolation uniquely identifies single API rule violation
+type apiViolation struct {
+ // Name of rule from APIRule.Name()
+ rule string
+
+ packageName string
+ typeName string
+
+ // Optional: name of field that violates API rule. Empty fieldName implies that
+ // the entire type violates the rule.
+ field string
+}
+
+// APIRule is the interface for validating API rule on Go types
+type APIRule interface {
+ // Validate evaluates API rule on type t and returns a list of field names in
+ // the type that violate the rule. Empty field name [""] implies the entire
+ // type violates the rule.
+ Validate(t *types.Type) ([]string, error)
+
+ // Name returns the name of APIRule
+ Name() string
+}
+
+// validate runs all API rules on type t and records any API rule violation
+func (l *apiLinter) validate(t *types.Type) error {
+ for _, r := range l.rules {
+ glog.V(5).Infof("validating API rule %v for type %v", r.Name(), t)
+ fields, err := r.Validate(t)
+ if err != nil {
+ return err
+ }
+ for _, field := range fields {
+ l.violations = append(l.violations, apiViolation{
+ rule: r.Name(),
+ packageName: t.Name.Package,
+ typeName: t.Name.Name,
+ field: field,
+ })
+ }
+ }
+ return nil
+}
+
+// report prints any API rule violation to writer w and returns error if violation exists
+func (l *apiLinter) report(w io.Writer) error {
+ for _, v := range l.violations {
+ fmt.Fprintf(w, "API rule violation: %s,%s,%s,%s\n", v.rule, v.packageName, v.typeName, v.field)
+ }
+ if len(l.violations) > 0 {
+ return fmt.Errorf("API rule violations exist")
+ }
+ return nil
+}
diff --git a/metrics-server/vendor/k8s.io/kube-openapi/pkg/generators/extension.go b/metrics-server/vendor/k8s.io/kube-openapi/pkg/generators/extension.go
new file mode 100644
index 0000000..befe38d
--- /dev/null
+++ b/metrics-server/vendor/k8s.io/kube-openapi/pkg/generators/extension.go
@@ -0,0 +1,182 @@
+/*
+Copyright 2018 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 generators
+
+import (
+ "fmt"
+ "sort"
+ "strings"
+
+ "k8s.io/gengo/examples/set-gen/sets"
+ "k8s.io/gengo/types"
+)
+
+const extensionPrefix = "x-kubernetes-"
+
+// extensionAttributes encapsulates common traits for particular extensions.
+type extensionAttributes struct {
+ xName string
+ kind types.Kind
+ allowedValues sets.String
+}
+
+// Extension tag to openapi extension attributes
+var tagToExtension = map[string]extensionAttributes{
+ "patchMergeKey": extensionAttributes{
+ xName: "x-kubernetes-patch-merge-key",
+ kind: types.Slice,
+ },
+ "patchStrategy": extensionAttributes{
+ xName: "x-kubernetes-patch-strategy",
+ kind: types.Slice,
+ allowedValues: sets.NewString("merge", "retainKeys"),
+ },
+ "listMapKey": extensionAttributes{
+ xName: "x-kubernetes-list-map-keys",
+ kind: types.Slice,
+ },
+ "listType": extensionAttributes{
+ xName: "x-kubernetes-list-type",
+ kind: types.Slice,
+ allowedValues: sets.NewString("atomic", "set", "map"),
+ },
+}
+
+// Extension encapsulates information necessary to generate an OpenAPI extension.
+type extension struct {
+ idlTag string // Example: listType
+ xName string // Example: x-kubernetes-list-type
+ values []string // Example: [atomic]
+}
+
+func (e extension) hasAllowedValues() bool {
+ return tagToExtension[e.idlTag].allowedValues.Len() > 0
+}
+
+func (e extension) allowedValues() sets.String {
+ return tagToExtension[e.idlTag].allowedValues
+}
+
+func (e extension) hasKind() bool {
+ return len(tagToExtension[e.idlTag].kind) > 0
+}
+
+func (e extension) kind() types.Kind {
+ return tagToExtension[e.idlTag].kind
+}
+
+func (e extension) validateAllowedValues() error {
+ // allowedValues not set means no restrictions on values.
+ if !e.hasAllowedValues() {
+ return nil
+ }
+ // Check for missing value.
+ if len(e.values) == 0 {
+ return fmt.Errorf("%s needs a value, none given.", e.idlTag)
+ }
+ // For each extension value, validate that it is allowed.
+ allowedValues := e.allowedValues()
+ if !allowedValues.HasAll(e.values...) {
+ return fmt.Errorf("%v not allowed for %s. Allowed values: %v",
+ e.values, e.idlTag, allowedValues.List())
+ }
+ return nil
+}
+
+func (e extension) validateType(kind types.Kind) error {
+ // If this extension class has no kind, then don't validate the type.
+ if !e.hasKind() {
+ return nil
+ }
+ if kind != e.kind() {
+ return fmt.Errorf("tag %s on type %v; only allowed on type %v",
+ e.idlTag, kind, e.kind())
+ }
+ return nil
+}
+
+func (e extension) hasMultipleValues() bool {
+ return len(e.values) > 1
+}
+
+// Returns sorted list of map keys. Needed for deterministic testing.
+func sortedMapKeys(m map[string][]string) []string {
+ keys := make([]string, len(m))
+ i := 0
+ for k := range m {
+ keys[i] = k
+ i++
+ }
+ sort.Strings(keys)
+ return keys
+}
+
+// Parses comments to return openapi extensions. Returns a list of
+// extensions which parsed correctly, as well as a list of the
+// parse errors. Validating extensions is performed separately.
+// NOTE: Non-empty errors does not mean extensions is empty.
+func parseExtensions(comments []string) ([]extension, []error) {
+ extensions := []extension{}
+ errors := []error{}
+ // First, generate extensions from "+k8s:openapi-gen=x-kubernetes-*" annotations.
+ values := getOpenAPITagValue(comments)
+ for _, val := range values {
+ // Example: x-kubernetes-member-tag:member_test
+ if strings.HasPrefix(val, extensionPrefix) {
+ parts := strings.SplitN(val, ":", 2)
+ if len(parts) != 2 {
+ errors = append(errors, fmt.Errorf("invalid extension value: %v", val))
+ continue
+ }
+ e := extension{
+ idlTag: tagName, // Example: k8s:openapi-gen
+ xName: parts[0], // Example: x-kubernetes-member-tag
+ values: []string{parts[1]}, // Example: member_test
+ }
+ extensions = append(extensions, e)
+ }
+ }
+ // Next, generate extensions from "idlTags" (e.g. +listType)
+ tagValues := types.ExtractCommentTags("+", comments)
+ for _, idlTag := range sortedMapKeys(tagValues) {
+ xAttrs, exists := tagToExtension[idlTag]
+ if !exists {
+ continue
+ }
+ values := tagValues[idlTag]
+ e := extension{
+ idlTag: idlTag, // listType
+ xName: xAttrs.xName, // x-kubernetes-list-type
+ values: values, // [atomic]
+ }
+ extensions = append(extensions, e)
+ }
+ return extensions, errors
+}
+
+func validateMemberExtensions(extensions []extension, m *types.Member) []error {
+ errors := []error{}
+ for _, e := range extensions {
+ if err := e.validateAllowedValues(); err != nil {
+ errors = append(errors, err)
+ }
+ if err := e.validateType(m.Type.Kind); err != nil {
+ errors = append(errors, err)
+ }
+ }
+ return errors
+}
diff --git a/metrics-server/vendor/k8s.io/kube-openapi/pkg/generators/openapi.go b/metrics-server/vendor/k8s.io/kube-openapi/pkg/generators/openapi.go
new file mode 100644
index 0000000..d6c6275
--- /dev/null
+++ b/metrics-server/vendor/k8s.io/kube-openapi/pkg/generators/openapi.go
@@ -0,0 +1,704 @@
+/*
+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 generators
+
+import (
+ "bytes"
+ "fmt"
+ "io"
+ "os"
+ "path/filepath"
+ "reflect"
+ "sort"
+ "strings"
+
+ "k8s.io/gengo/args"
+ "k8s.io/gengo/generator"
+ "k8s.io/gengo/namer"
+ "k8s.io/gengo/types"
+ generatorargs "k8s.io/kube-openapi/cmd/openapi-gen/args"
+ openapi "k8s.io/kube-openapi/pkg/common"
+
+ "github.com/golang/glog"
+)
+
+// This is the comment tag that carries parameters for open API generation.
+const tagName = "k8s:openapi-gen"
+const tagOptional = "optional"
+
+// Known values for the tag.
+const (
+ tagValueTrue = "true"
+ tagValueFalse = "false"
+)
+
+// Used for temporary validation of patch struct tags.
+// TODO: Remove patch struct tag validation because they we are now consuming OpenAPI on server.
+var tempPatchTags = [...]string{
+ "patchMergeKey",
+ "patchStrategy",
+}
+
+func getOpenAPITagValue(comments []string) []string {
+ return types.ExtractCommentTags("+", comments)[tagName]
+}
+
+func getSingleTagsValue(comments []string, tag string) (string, error) {
+ tags, ok := types.ExtractCommentTags("+", comments)[tag]
+ if !ok || len(tags) == 0 {
+ return "", nil
+ }
+ if len(tags) > 1 {
+ return "", fmt.Errorf("multiple values are not allowed for tag %s", tag)
+ }
+ return tags[0], nil
+}
+
+func hasOpenAPITagValue(comments []string, value string) bool {
+ tagValues := getOpenAPITagValue(comments)
+ for _, val := range tagValues {
+ if val == value {
+ return true
+ }
+ }
+ return false
+}
+
+// hasOptionalTag returns true if the member has +optional in its comments or
+// omitempty in its json tags.
+func hasOptionalTag(m *types.Member) bool {
+ hasOptionalCommentTag := types.ExtractCommentTags(
+ "+", m.CommentLines)[tagOptional] != nil
+ hasOptionalJsonTag := strings.Contains(
+ reflect.StructTag(m.Tags).Get("json"), "omitempty")
+ return hasOptionalCommentTag || hasOptionalJsonTag
+}
+
+type identityNamer struct{}
+
+func (_ identityNamer) Name(t *types.Type) string {
+ return t.Name.String()
+}
+
+var _ namer.Namer = identityNamer{}
+
+// NameSystems returns the name system used by the generators in this package.
+func NameSystems() namer.NameSystems {
+ return namer.NameSystems{
+ "raw": namer.NewRawNamer("", nil),
+ "sorting_namer": identityNamer{},
+ }
+}
+
+// DefaultNameSystem returns the default name system for ordering the types to be
+// processed by the generators in this package.
+func DefaultNameSystem() string {
+ return "sorting_namer"
+}
+
+func Packages(context *generator.Context, arguments *args.GeneratorArgs) generator.Packages {
+ boilerplate, err := arguments.LoadGoBoilerplate()
+ if err != nil {
+ glog.Fatalf("Failed loading boilerplate: %v", err)
+ }
+ header := append([]byte(fmt.Sprintf("// +build !%s\n\n", arguments.GeneratedBuildTag)), boilerplate...)
+ header = append(header, []byte(
+ `
+// This file was autogenerated by openapi-gen. Do not edit it manually!
+
+`)...)
+
+ reportFilename := "-"
+ if customArgs, ok := arguments.CustomArgs.(*generatorargs.CustomArgs); ok {
+ reportFilename = customArgs.ReportFilename
+ }
+
+ return generator.Packages{
+ &generator.DefaultPackage{
+ PackageName: filepath.Base(arguments.OutputPackagePath),
+ PackagePath: arguments.OutputPackagePath,
+ HeaderText: header,
+ GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) {
+ return []generator.Generator{NewOpenAPIGen(arguments.OutputFileBaseName, arguments.OutputPackagePath, context, newAPILinter(), reportFilename)}
+ },
+ FilterFunc: func(c *generator.Context, t *types.Type) bool {
+ // There is a conflict between this codegen and codecgen, we should avoid types generated for codecgen
+ if strings.HasPrefix(t.Name.Name, "codecSelfer") {
+ return false
+ }
+ pkg := context.Universe.Package(t.Name.Package)
+ if hasOpenAPITagValue(pkg.Comments, tagValueTrue) {
+ return !hasOpenAPITagValue(t.CommentLines, tagValueFalse)
+ }
+ if hasOpenAPITagValue(t.CommentLines, tagValueTrue) {
+ return true
+ }
+ return false
+ },
+ },
+ }
+}
+
+const (
+ specPackagePath = "github.com/go-openapi/spec"
+ openAPICommonPackagePath = "k8s.io/kube-openapi/pkg/common"
+)
+
+// openApiGen produces a file with auto-generated OpenAPI functions.
+type openAPIGen struct {
+ generator.DefaultGen
+ // TargetPackage is the package that will get GetOpenAPIDefinitions function returns all open API definitions.
+ targetPackage string
+ imports namer.ImportTracker
+ types []*types.Type
+ context *generator.Context
+ linter *apiLinter
+ reportFilename string
+}
+
+func NewOpenAPIGen(sanitizedName string, targetPackage string, context *generator.Context, linter *apiLinter, reportFilename string) generator.Generator {
+ return &openAPIGen{
+ DefaultGen: generator.DefaultGen{
+ OptionalName: sanitizedName,
+ },
+ imports: generator.NewImportTracker(),
+ targetPackage: targetPackage,
+ context: context,
+ linter: linter,
+ reportFilename: reportFilename,
+ }
+}
+
+const nameTmpl = "schema_$.type|private$"
+
+func (g *openAPIGen) Namers(c *generator.Context) namer.NameSystems {
+ // Have the raw namer for this file track what it imports.
+ return namer.NameSystems{
+ "raw": namer.NewRawNamer(g.targetPackage, g.imports),
+ "private": &namer.NameStrategy{
+ Join: func(pre string, in []string, post string) string {
+ return strings.Join(in, "_")
+ },
+ PrependPackageNames: 4, // enough to fully qualify from k8s.io/api/...
+ },
+ }
+}
+
+func (g *openAPIGen) Filter(c *generator.Context, t *types.Type) bool {
+ // There is a conflict between this codegen and codecgen, we should avoid types generated for codecgen
+ if strings.HasPrefix(t.Name.Name, "codecSelfer") {
+ return false
+ }
+ g.types = append(g.types, t)
+ return true
+}
+
+func (g *openAPIGen) isOtherPackage(pkg string) bool {
+ if pkg == g.targetPackage {
+ return false
+ }
+ if strings.HasSuffix(pkg, "\""+g.targetPackage+"\"") {
+ return false
+ }
+ return true
+}
+
+func (g *openAPIGen) Imports(c *generator.Context) []string {
+ importLines := []string{}
+ for _, singleImport := range g.imports.ImportLines() {
+ importLines = append(importLines, singleImport)
+ }
+ return importLines
+}
+
+func argsFromType(t *types.Type) generator.Args {
+ return generator.Args{
+ "type": t,
+ "ReferenceCallback": types.Ref(openAPICommonPackagePath, "ReferenceCallback"),
+ "OpenAPIDefinition": types.Ref(openAPICommonPackagePath, "OpenAPIDefinition"),
+ "SpecSchemaType": types.Ref(specPackagePath, "Schema"),
+ }
+}
+
+func (g *openAPIGen) Init(c *generator.Context, w io.Writer) error {
+ sw := generator.NewSnippetWriter(w, c, "$", "$")
+ sw.Do("func GetOpenAPIDefinitions(ref $.ReferenceCallback|raw$) map[string]$.OpenAPIDefinition|raw$ {\n", argsFromType(nil))
+ sw.Do("return map[string]$.OpenAPIDefinition|raw${\n", argsFromType(nil))
+
+ for _, t := range g.types {
+ err := newOpenAPITypeWriter(sw).generateCall(t)
+ if err != nil {
+ return err
+ }
+ }
+
+ sw.Do("}\n", nil)
+ sw.Do("}\n\n", nil)
+
+ return sw.Error()
+}
+
+func (g *openAPIGen) GenerateType(c *generator.Context, t *types.Type, w io.Writer) error {
+ glog.V(5).Infof("validating API rules for type %v", t)
+ if err := g.linter.validate(t); err != nil {
+ return err
+ }
+ glog.V(5).Infof("generating for type %v", t)
+ sw := generator.NewSnippetWriter(w, c, "$", "$")
+ err := newOpenAPITypeWriter(sw).generate(t)
+ if err != nil {
+ return err
+ }
+ return sw.Error()
+}
+
+func getJsonTags(m *types.Member) []string {
+ jsonTag := reflect.StructTag(m.Tags).Get("json")
+ if jsonTag == "" {
+ return []string{}
+ }
+ return strings.Split(jsonTag, ",")
+}
+
+func getReferableName(m *types.Member) string {
+ jsonTags := getJsonTags(m)
+ if len(jsonTags) > 0 {
+ if jsonTags[0] == "-" {
+ return ""
+ } else {
+ return jsonTags[0]
+ }
+ } else {
+ return m.Name
+ }
+}
+
+func shouldInlineMembers(m *types.Member) bool {
+ jsonTags := getJsonTags(m)
+ return len(jsonTags) > 1 && jsonTags[1] == "inline"
+}
+
+type openAPITypeWriter struct {
+ *generator.SnippetWriter
+ refTypes map[string]*types.Type
+ GetDefinitionInterface *types.Type
+}
+
+func newOpenAPITypeWriter(sw *generator.SnippetWriter) openAPITypeWriter {
+ return openAPITypeWriter{
+ SnippetWriter: sw,
+ refTypes: map[string]*types.Type{},
+ }
+}
+
+func methodReturnsValue(mt *types.Type, pkg, name string) bool {
+ if len(mt.Signature.Parameters) != 0 || len(mt.Signature.Results) != 1 {
+ return false
+ }
+ r := mt.Signature.Results[0]
+ return r.Name.Name == name && r.Name.Package == pkg
+}
+
+func hasOpenAPIDefinitionMethod(t *types.Type) bool {
+ for mn, mt := range t.Methods {
+ if mn != "OpenAPIDefinition" {
+ continue
+ }
+ return methodReturnsValue(mt, openAPICommonPackagePath, "OpenAPIDefinition")
+ }
+ return false
+}
+
+func hasOpenAPIDefinitionMethods(t *types.Type) bool {
+ var hasSchemaTypeMethod, hasOpenAPISchemaFormat bool
+ for mn, mt := range t.Methods {
+ switch mn {
+ case "OpenAPISchemaType":
+ hasSchemaTypeMethod = methodReturnsValue(mt, "", "[]string")
+ case "OpenAPISchemaFormat":
+ hasOpenAPISchemaFormat = methodReturnsValue(mt, "", "string")
+ }
+ }
+ return hasSchemaTypeMethod && hasOpenAPISchemaFormat
+}
+
+// typeShortName returns short package name (e.g. the name x appears in package x definition) dot type name.
+func typeShortName(t *types.Type) string {
+ return filepath.Base(t.Name.Package) + "." + t.Name.Name
+}
+
+func (g openAPITypeWriter) generateMembers(t *types.Type, required []string) ([]string, error) {
+ var err error
+ for _, m := range t.Members {
+ if hasOpenAPITagValue(m.CommentLines, tagValueFalse) {
+ continue
+ }
+ if shouldInlineMembers(&m) {
+ required, err = g.generateMembers(m.Type, required)
+ if err != nil {
+ return required, err
+ }
+ continue
+ }
+ name := getReferableName(&m)
+ if name == "" {
+ continue
+ }
+ if !hasOptionalTag(&m) {
+ required = append(required, name)
+ }
+ if err = g.generateProperty(&m, t); err != nil {
+ glog.Errorf("Error when generating: %v, %v\n", name, m)
+ return required, err
+ }
+ }
+ return required, nil
+}
+
+func (g openAPITypeWriter) generateCall(t *types.Type) error {
+ // Only generate for struct type and ignore the rest
+ switch t.Kind {
+ case types.Struct:
+ args := argsFromType(t)
+ g.Do("\"$.$\": ", t.Name)
+ if hasOpenAPIDefinitionMethod(t) {
+ g.Do("$.type|raw${}.OpenAPIDefinition(),\n", args)
+ } else {
+ g.Do(nameTmpl+"(ref),\n", args)
+ }
+ }
+ return g.Error()
+}
+
+func (g openAPITypeWriter) generate(t *types.Type) error {
+ // Only generate for struct type and ignore the rest
+ switch t.Kind {
+ case types.Struct:
+ if hasOpenAPIDefinitionMethod(t) {
+ // already invoked directly
+ return nil
+ }
+
+ args := argsFromType(t)
+ g.Do("func "+nameTmpl+"(ref $.ReferenceCallback|raw$) $.OpenAPIDefinition|raw$ {\n", args)
+ if hasOpenAPIDefinitionMethods(t) {
+ g.Do("return $.OpenAPIDefinition|raw${\n"+
+ "Schema: spec.Schema{\n"+
+ "SchemaProps: spec.SchemaProps{\n", args)
+ g.generateDescription(t.CommentLines)
+ g.Do("Type:$.type|raw${}.OpenAPISchemaType(),\n"+
+ "Format:$.type|raw${}.OpenAPISchemaFormat(),\n"+
+ "},\n"+
+ "},\n"+
+ "}\n}\n\n", args)
+ return nil
+ }
+ g.Do("return $.OpenAPIDefinition|raw${\nSchema: spec.Schema{\nSchemaProps: spec.SchemaProps{\n", args)
+ g.generateDescription(t.CommentLines)
+ g.Do("Properties: map[string]$.SpecSchemaType|raw${\n", args)
+ required, err := g.generateMembers(t, []string{})
+ if err != nil {
+ return err
+ }
+ g.Do("},\n", nil)
+ if len(required) > 0 {
+ g.Do("Required: []string{\"$.$\"},\n", strings.Join(required, "\",\""))
+ }
+ g.Do("},\n", nil)
+ if err := g.generateStructExtensions(t); err != nil {
+ return err
+ }
+ g.Do("},\n", nil)
+ g.Do("Dependencies: []string{\n", args)
+ // Map order is undefined, sort them or we may get a different file generated each time.
+ keys := []string{}
+ for k := range g.refTypes {
+ keys = append(keys, k)
+ }
+ sort.Strings(keys)
+ for _, k := range keys {
+ v := g.refTypes[k]
+ if t, _ := openapi.GetOpenAPITypeFormat(v.String()); t != "" {
+ // This is a known type, we do not need a reference to it
+ // Will eliminate special case of time.Time
+ continue
+ }
+ g.Do("\"$.$\",", k)
+ }
+ g.Do("},\n}\n}\n\n", nil)
+ }
+ return nil
+}
+
+func (g openAPITypeWriter) generateStructExtensions(t *types.Type) error {
+ extensions, errors := parseExtensions(t.CommentLines)
+ // Initially, we will only log struct extension errors.
+ if len(errors) > 0 {
+ for _, e := range errors {
+ glog.V(2).Infof("[%s]: %s\n", t.String(), e)
+ }
+ }
+ // TODO(seans3): Validate struct extensions here.
+ g.emitExtensions(extensions)
+ return nil
+}
+
+func (g openAPITypeWriter) generateMemberExtensions(m *types.Member, parent *types.Type) error {
+ extensions, parseErrors := parseExtensions(m.CommentLines)
+ validationErrors := validateMemberExtensions(extensions, m)
+ errors := append(parseErrors, validationErrors...)
+ // Initially, we will only log member extension errors.
+ if len(errors) > 0 {
+ errorPrefix := fmt.Sprintf("[%s] %s:", parent.String(), m.String())
+ for _, e := range errors {
+ glog.V(2).Infof("%s %s\n", errorPrefix, e)
+ }
+ }
+ g.emitExtensions(extensions)
+ return nil
+}
+
+func (g openAPITypeWriter) emitExtensions(extensions []extension) {
+ // If any extensions exist, then emit code to create them.
+ if len(extensions) == 0 {
+ return
+ }
+ g.Do("VendorExtensible: spec.VendorExtensible{\nExtensions: spec.Extensions{\n", nil)
+ for _, extension := range extensions {
+ g.Do("\"$.$\": ", extension.xName)
+ if extension.hasMultipleValues() {
+ g.Do("[]string{\n", nil)
+ }
+ for _, value := range extension.values {
+ g.Do("\"$.$\",\n", value)
+ }
+ if extension.hasMultipleValues() {
+ g.Do("},\n", nil)
+ }
+ }
+ g.Do("},\n},\n", nil)
+}
+
+// TODO(#44005): Move this validation outside of this generator (probably to policy verifier)
+func (g openAPITypeWriter) validatePatchTags(m *types.Member, parent *types.Type) error {
+ // TODO: Remove patch struct tag validation because they we are now consuming OpenAPI on server.
+ for _, tagKey := range tempPatchTags {
+ structTagValue := reflect.StructTag(m.Tags).Get(tagKey)
+ commentTagValue, err := getSingleTagsValue(m.CommentLines, tagKey)
+ if err != nil {
+ return err
+ }
+ if structTagValue != commentTagValue {
+ return fmt.Errorf("Tags in comment and struct should match for member (%s) of (%s)",
+ m.Name, parent.Name.String())
+ }
+ }
+ return nil
+}
+
+func (g openAPITypeWriter) generateDescription(CommentLines []string) {
+ var buffer bytes.Buffer
+ delPrevChar := func() {
+ if buffer.Len() > 0 {
+ buffer.Truncate(buffer.Len() - 1) // Delete the last " " or "\n"
+ }
+ }
+
+ for _, line := range CommentLines {
+ // Ignore all lines after ---
+ if line == "---" {
+ break
+ }
+ line = strings.TrimRight(line, " ")
+ leading := strings.TrimLeft(line, " ")
+ switch {
+ case len(line) == 0: // Keep paragraphs
+ delPrevChar()
+ buffer.WriteString("\n\n")
+ case strings.HasPrefix(leading, "TODO"): // Ignore one line TODOs
+ case strings.HasPrefix(leading, "+"): // Ignore instructions to go2idl
+ default:
+ if strings.HasPrefix(line, " ") || strings.HasPrefix(line, "\t") {
+ delPrevChar()
+ line = "\n" + line + "\n" // Replace it with newline. This is useful when we have a line with: "Example:\n\tJSON-someting..."
+ } else {
+ line += " "
+ }
+ buffer.WriteString(line)
+ }
+ }
+
+ postDoc := strings.TrimRight(buffer.String(), "\n")
+ postDoc = strings.Replace(postDoc, "\\\"", "\"", -1) // replace user's \" to "
+ postDoc = strings.Replace(postDoc, "\"", "\\\"", -1) // Escape "
+ postDoc = strings.Replace(postDoc, "\n", "\\n", -1)
+ postDoc = strings.Replace(postDoc, "\t", "\\t", -1)
+ postDoc = strings.Trim(postDoc, " ")
+ if postDoc != "" {
+ g.Do("Description: \"$.$\",\n", postDoc)
+ }
+}
+
+func (g openAPITypeWriter) generateProperty(m *types.Member, parent *types.Type) error {
+ name := getReferableName(m)
+ if name == "" {
+ return nil
+ }
+ if err := g.validatePatchTags(m, parent); err != nil {
+ return err
+ }
+ g.Do("\"$.$\": {\n", name)
+ if err := g.generateMemberExtensions(m, parent); err != nil {
+ return err
+ }
+ g.Do("SchemaProps: spec.SchemaProps{\n", nil)
+ g.generateDescription(m.CommentLines)
+ jsonTags := getJsonTags(m)
+ if len(jsonTags) > 1 && jsonTags[1] == "string" {
+ g.generateSimpleProperty("string", "")
+ g.Do("},\n},\n", nil)
+ return nil
+ }
+ t := resolveAliasAndPtrType(m.Type)
+ // If we can get a openAPI type and format for this type, we consider it to be simple property
+ typeString, format := openapi.GetOpenAPITypeFormat(t.String())
+ if typeString != "" {
+ g.generateSimpleProperty(typeString, format)
+ g.Do("},\n},\n", nil)
+ return nil
+ }
+ switch t.Kind {
+ case types.Builtin:
+ return fmt.Errorf("please add type %v to getOpenAPITypeFormat function", t)
+ case types.Map:
+ if err := g.generateMapProperty(t); err != nil {
+ return err
+ }
+ case types.Slice, types.Array:
+ if err := g.generateSliceProperty(t); err != nil {
+ return err
+ }
+ case types.Struct, types.Interface:
+ g.generateReferenceProperty(t)
+ default:
+ return fmt.Errorf("cannot generate spec for type %v", t)
+ }
+ g.Do("},\n},\n", nil)
+ return g.Error()
+}
+
+func (g openAPITypeWriter) generateSimpleProperty(typeString, format string) {
+ g.Do("Type: []string{\"$.$\"},\n", typeString)
+ g.Do("Format: \"$.$\",\n", format)
+}
+
+func (g openAPITypeWriter) generateReferenceProperty(t *types.Type) {
+ g.refTypes[t.Name.String()] = t
+ g.Do("Ref: ref(\"$.$\"),\n", t.Name.String())
+}
+
+func resolveAliasAndPtrType(t *types.Type) *types.Type {
+ var prev *types.Type
+ for prev != t {
+ prev = t
+ if t.Kind == types.Alias {
+ t = t.Underlying
+ }
+ if t.Kind == types.Pointer {
+ t = t.Elem
+ }
+ }
+ return t
+}
+
+func (g openAPITypeWriter) generateMapProperty(t *types.Type) error {
+ keyType := resolveAliasAndPtrType(t.Key)
+ elemType := resolveAliasAndPtrType(t.Elem)
+
+ // According to OpenAPI examples, only map from string is supported
+ if keyType.Name.Name != "string" {
+ return fmt.Errorf("map with non-string keys are not supported by OpenAPI in %v", t)
+ }
+ g.Do("Type: []string{\"object\"},\n", nil)
+ g.Do("AdditionalProperties: &spec.SchemaOrBool{\nSchema: &spec.Schema{\nSchemaProps: spec.SchemaProps{\n", nil)
+ typeString, format := openapi.GetOpenAPITypeFormat(elemType.String())
+ if typeString != "" {
+ g.generateSimpleProperty(typeString, format)
+ g.Do("},\n},\n},\n", nil)
+ return nil
+ }
+ switch elemType.Kind {
+ case types.Builtin:
+ return fmt.Errorf("please add type %v to getOpenAPITypeFormat function", elemType)
+ case types.Struct:
+ g.generateReferenceProperty(elemType)
+ case types.Slice, types.Array:
+ g.generateSliceProperty(elemType)
+ default:
+ return fmt.Errorf("map Element kind %v is not supported in %v", elemType.Kind, t.Name)
+ }
+ g.Do("},\n},\n},\n", nil)
+ return nil
+}
+
+func (g openAPITypeWriter) generateSliceProperty(t *types.Type) error {
+ elemType := resolveAliasAndPtrType(t.Elem)
+ g.Do("Type: []string{\"array\"},\n", nil)
+ g.Do("Items: &spec.SchemaOrArray{\nSchema: &spec.Schema{\nSchemaProps: spec.SchemaProps{\n", nil)
+ typeString, format := openapi.GetOpenAPITypeFormat(elemType.String())
+ if typeString != "" {
+ g.generateSimpleProperty(typeString, format)
+ g.Do("},\n},\n},\n", nil)
+ return nil
+ }
+ switch elemType.Kind {
+ case types.Builtin:
+ return fmt.Errorf("please add type %v to getOpenAPITypeFormat function", elemType)
+ case types.Struct:
+ g.generateReferenceProperty(elemType)
+ case types.Slice, types.Array:
+ g.generateSliceProperty(elemType)
+ default:
+ return fmt.Errorf("slice Element kind %v is not supported in %v", elemType.Kind, t)
+ }
+ g.Do("},\n},\n},\n", nil)
+ return nil
+}
+
+// Finalize prints the API rule violations to report file (if specified from arguments) or stdout (default)
+func (g *openAPIGen) Finalize(c *generator.Context, w io.Writer) error {
+ // If report file isn't specified, return error to force user to choose either stdout ("-") or a file name
+ if len(g.reportFilename) == 0 {
+ return fmt.Errorf("empty report file name: please provide a valid file name or use the default \"-\" (stdout)")
+ }
+ // If stdout is specified, print violations and return error
+ if g.reportFilename == "-" {
+ return g.linter.report(os.Stdout)
+ }
+ // Otherwise, print violations to report file and return nil
+ f, err := os.Create(g.reportFilename)
+ if err != nil {
+ return err
+ }
+ defer f.Close()
+ g.linter.report(f)
+ // NOTE: we don't return error here because we assume that the report file will
+ // get evaluated afterwards to determine if error should be raised. For example,
+ // you can have make rules that compare the report file with existing known
+ // violations (whitelist) and determine no error if no change is detected.
+ return nil
+}
diff --git a/metrics-server/vendor/k8s.io/kube-openapi/pkg/generators/rules/doc.go b/metrics-server/vendor/k8s.io/kube-openapi/pkg/generators/rules/doc.go
new file mode 100644
index 0000000..384a44d
--- /dev/null
+++ b/metrics-server/vendor/k8s.io/kube-openapi/pkg/generators/rules/doc.go
@@ -0,0 +1,23 @@
+/*
+Copyright 2018 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 rules contains API rules that are enforced in OpenAPI spec generation
+// as part of the machinery. Files under this package implement APIRule interface
+// which evaluates Go type and produces list of API rule violations.
+//
+// Implementations of APIRule should be added to API linter under openAPIGen code-
+// generator to get integrated in the generation process.
+package rules
diff --git a/metrics-server/vendor/k8s.io/kube-openapi/pkg/generators/rules/names_match.go b/metrics-server/vendor/k8s.io/kube-openapi/pkg/generators/rules/names_match.go
new file mode 100644
index 0000000..edd3b5e
--- /dev/null
+++ b/metrics-server/vendor/k8s.io/kube-openapi/pkg/generators/rules/names_match.go
@@ -0,0 +1,171 @@
+/*
+Copyright 2018 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 rules
+
+import (
+ "reflect"
+ "strings"
+
+ "k8s.io/apimachinery/pkg/util/sets"
+ "k8s.io/gengo/types"
+)
+
+var (
+ // Blacklist of JSON tags that should skip match evaluation
+ jsonTagBlacklist = sets.NewString(
+ // Omitted field is ignored by the package
+ "-",
+ )
+
+ // Blacklist of JSON names that should skip match evaluation
+ jsonNameBlacklist = sets.NewString(
+ // Empty name is used for inline struct field (e.g. metav1.TypeMeta)
+ "",
+ // Special case for object and list meta
+ "metadata",
+ )
+
+ // List of substrings that aren't allowed in Go name and JSON name
+ disallowedNameSubstrings = sets.NewString(
+ // Underscore is not allowed in either name
+ "_",
+ // Dash is not allowed in either name. Note that since dash is a valid JSON tag, this should be checked
+ // after JSON tag blacklist check.
+ "-",
+ )
+)
+
+/*
+NamesMatch implements APIRule interface.
+Go field names must be CamelCase. JSON field names must be camelCase. Other than capitalization of the
+initial letter, the two should almost always match. No underscores nor dashes in either.
+This rule verifies the convention "Other than capitalization of the initial letter, the two should almost always match."
+Examples (also in unit test):
+ Go name | JSON name | match
+ podSpec false
+ PodSpec podSpec true
+ PodSpec PodSpec false
+ podSpec podSpec false
+ PodSpec spec false
+ Spec podSpec false
+ JSONSpec jsonSpec true
+ JSONSpec jsonspec false
+ HTTPJSONSpec httpJSONSpec true
+NOTE: this validator cannot tell two sequential all-capital words from one word, therefore the case below
+is also considered matched.
+ HTTPJSONSpec httpjsonSpec true
+NOTE: JSON names in jsonNameBlacklist should skip evaluation
+ true
+ podSpec true
+ podSpec - true
+ podSpec metadata true
+*/
+type NamesMatch struct{}
+
+// Name returns the name of APIRule
+func (n *NamesMatch) Name() string {
+ return "names_match"
+}
+
+// Validate evaluates API rule on type t and returns a list of field names in
+// the type that violate the rule. Empty field name [""] implies the entire
+// type violates the rule.
+func (n *NamesMatch) Validate(t *types.Type) ([]string, error) {
+ fields := make([]string, 0)
+
+ // Only validate struct type and ignore the rest
+ switch t.Kind {
+ case types.Struct:
+ for _, m := range t.Members {
+ goName := m.Name
+ jsonTag, ok := reflect.StructTag(m.Tags).Lookup("json")
+ // Distinguish empty JSON tag and missing JSON tag. Empty JSON tag / name is
+ // allowed (in JSON name blacklist) but missing JSON tag is invalid.
+ if !ok {
+ fields = append(fields, goName)
+ continue
+ }
+ if jsonTagBlacklist.Has(jsonTag) {
+ continue
+ }
+ jsonName := strings.Split(jsonTag, ",")[0]
+ if !namesMatch(goName, jsonName) {
+ fields = append(fields, goName)
+ }
+ }
+ }
+ return fields, nil
+}
+
+// namesMatch evaluates if goName and jsonName match the API rule
+// TODO: Use an off-the-shelf CamelCase solution instead of implementing this logic. The following existing
+// packages have been tried out:
+// github.com/markbates/inflect
+// github.com/segmentio/go-camelcase
+// github.com/iancoleman/strcase
+// github.com/fatih/camelcase
+// Please see https://github.com/kubernetes/kube-openapi/pull/83#issuecomment-400842314 for more details
+// about why they don't satisfy our need. What we need can be a function that detects an acronym at the
+// beginning of a string.
+func namesMatch(goName, jsonName string) bool {
+ if jsonNameBlacklist.Has(jsonName) {
+ return true
+ }
+ if !isAllowedName(goName) || !isAllowedName(jsonName) {
+ return false
+ }
+ if strings.ToLower(goName) != strings.ToLower(jsonName) {
+ return false
+ }
+ // Go field names must be CamelCase. JSON field names must be camelCase.
+ if !isCapital(goName[0]) || isCapital(jsonName[0]) {
+ return false
+ }
+ for i := 0; i < len(goName); i++ {
+ if goName[i] == jsonName[i] {
+ // goName[0:i-1] is uppercase and jsonName[0:i-1] is lowercase, goName[i:]
+ // and jsonName[i:] should match;
+ // goName[i] should be lowercase if i is equal to 1, e.g.:
+ // goName | jsonName
+ // PodSpec podSpec
+ // or uppercase if i is greater than 1, e.g.:
+ // goname | jsonName
+ // JSONSpec jsonSpec
+ // This is to rule out cases like:
+ // goname | jsonName
+ // JSONSpec jsonspec
+ return goName[i:] == jsonName[i:] && (i == 1 || isCapital(goName[i]))
+ }
+ }
+ return true
+}
+
+// isCaptical returns true if one character is capital
+func isCapital(b byte) bool {
+ return b >= 'A' && b <= 'Z'
+}
+
+// isAllowedName checks the list of disallowedNameSubstrings and returns true if name doesn't contain
+// any disallowed substring.
+func isAllowedName(name string) bool {
+ for _, substr := range disallowedNameSubstrings.UnsortedList() {
+ if strings.Contains(name, substr) {
+ return false
+ }
+ }
+ return true
+}
diff --git a/metrics-server/vendor/k8s.io/kube-openapi/pkg/handler/handler.go b/metrics-server/vendor/k8s.io/kube-openapi/pkg/handler/handler.go
new file mode 100644
index 0000000..c4bbc0b
--- /dev/null
+++ b/metrics-server/vendor/k8s.io/kube-openapi/pkg/handler/handler.go
@@ -0,0 +1,272 @@
+/*
+Copyright 2017 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 handler
+
+import (
+ "bytes"
+ "compress/gzip"
+ "crypto/sha512"
+ "encoding/json"
+ "fmt"
+ "mime"
+ "net/http"
+ "strings"
+ "sync"
+ "time"
+
+ "bitbucket.org/ww/goautoneg"
+
+ yaml "gopkg.in/yaml.v2"
+
+ "github.com/NYTimes/gziphandler"
+ restful "github.com/emicklei/go-restful"
+ "github.com/go-openapi/spec"
+ "github.com/golang/protobuf/proto"
+ openapi_v2 "github.com/googleapis/gnostic/OpenAPIv2"
+ "github.com/googleapis/gnostic/compiler"
+
+ "k8s.io/kube-openapi/pkg/builder"
+ "k8s.io/kube-openapi/pkg/common"
+)
+
+const (
+ jsonExt = ".json"
+
+ mimeJson = "application/json"
+ // TODO(mehdy): change @68f4ded to a version tag when gnostic add version tags.
+ mimePb = "application/com.github.googleapis.gnostic.OpenAPIv2@68f4ded+protobuf"
+ mimePbGz = "application/x-gzip"
+)
+
+// OpenAPIService is the service responsible for serving OpenAPI spec. It has
+// the ability to safely change the spec while serving it.
+type OpenAPIService struct {
+ // rwMutex protects All members of this service.
+ rwMutex sync.RWMutex
+
+ lastModified time.Time
+
+ specBytes []byte
+ specPb []byte
+ specPbGz []byte
+
+ specBytesETag string
+ specPbETag string
+ specPbGzETag string
+}
+
+func init() {
+ mime.AddExtensionType(".json", mimeJson)
+ mime.AddExtensionType(".pb-v1", mimePb)
+ mime.AddExtensionType(".gz", mimePbGz)
+}
+
+func computeETag(data []byte) string {
+ return fmt.Sprintf("\"%X\"", sha512.Sum512(data))
+}
+
+// NOTE: [DEPRECATION] We will announce deprecation for format-separated endpoints for OpenAPI spec,
+// and switch to a single /openapi/v2 endpoint in Kubernetes 1.10. The design doc and deprecation process
+// are tracked at: https://docs.google.com/document/d/19lEqE9lc4yHJ3WJAJxS_G7TcORIJXGHyq3wpwcH28nU.
+//
+// BuildAndRegisterOpenAPIService builds the spec and registers a handler to provide access to it.
+// Use this method if your OpenAPI spec is static. If you want to update the spec, use BuildOpenAPISpec then RegisterOpenAPIService.
+func BuildAndRegisterOpenAPIService(servePath string, webServices []*restful.WebService, config *common.Config, handler common.PathHandler) (*OpenAPIService, error) {
+ spec, err := builder.BuildOpenAPISpec(webServices, config)
+ if err != nil {
+ return nil, err
+ }
+ return RegisterOpenAPIService(spec, servePath, handler)
+}
+
+// NOTE: [DEPRECATION] We will announce deprecation for format-separated endpoints for OpenAPI spec,
+// and switch to a single /openapi/v2 endpoint in Kubernetes 1.10. The design doc and deprecation process
+// are tracked at: https://docs.google.com/document/d/19lEqE9lc4yHJ3WJAJxS_G7TcORIJXGHyq3wpwcH28nU.
+//
+// RegisterOpenAPIService registers a handler to provide access to provided swagger spec.
+// Note: servePath should end with ".json" as the RegisterOpenAPIService assume it is serving a
+// json file and will also serve .pb and .gz files.
+func RegisterOpenAPIService(openapiSpec *spec.Swagger, servePath string, handler common.PathHandler) (*OpenAPIService, error) {
+ if !strings.HasSuffix(servePath, jsonExt) {
+ return nil, fmt.Errorf("serving path must end with \"%s\"", jsonExt)
+ }
+
+ servePathBase := strings.TrimSuffix(servePath, jsonExt)
+
+ o := OpenAPIService{}
+ if err := o.UpdateSpec(openapiSpec); err != nil {
+ return nil, err
+ }
+
+ type fileInfo struct {
+ ext string
+ getDataAndETag func() ([]byte, string, time.Time)
+ }
+
+ files := []fileInfo{
+ {".json", o.getSwaggerBytes},
+ {"-2.0.0.json", o.getSwaggerBytes},
+ {"-2.0.0.pb-v1", o.getSwaggerPbBytes},
+ {"-2.0.0.pb-v1.gz", o.getSwaggerPbGzBytes},
+ }
+
+ for _, file := range files {
+ path := servePathBase + file.ext
+ getDataAndETag := file.getDataAndETag
+ handler.Handle(path, gziphandler.GzipHandler(http.HandlerFunc(
+ func(w http.ResponseWriter, r *http.Request) {
+ data, etag, lastModified := getDataAndETag()
+ w.Header().Set("Etag", etag)
+
+ // ServeContent will take care of caching using eTag.
+ http.ServeContent(w, r, path, lastModified, bytes.NewReader(data))
+ }),
+ ))
+ }
+
+ return &o, nil
+}
+
+func (o *OpenAPIService) getSwaggerBytes() ([]byte, string, time.Time) {
+ o.rwMutex.RLock()
+ defer o.rwMutex.RUnlock()
+ return o.specBytes, o.specBytesETag, o.lastModified
+}
+
+func (o *OpenAPIService) getSwaggerPbBytes() ([]byte, string, time.Time) {
+ o.rwMutex.RLock()
+ defer o.rwMutex.RUnlock()
+ return o.specPb, o.specPbETag, o.lastModified
+}
+
+func (o *OpenAPIService) getSwaggerPbGzBytes() ([]byte, string, time.Time) {
+ o.rwMutex.RLock()
+ defer o.rwMutex.RUnlock()
+ return o.specPbGz, o.specPbGzETag, o.lastModified
+}
+
+func (o *OpenAPIService) UpdateSpec(openapiSpec *spec.Swagger) (err error) {
+ specBytes, err := json.MarshalIndent(openapiSpec, " ", " ")
+ if err != nil {
+ return err
+ }
+ specPb, err := toProtoBinary(specBytes)
+ if err != nil {
+ return err
+ }
+ specPbGz := toGzip(specPb)
+
+ specBytesETag := computeETag(specBytes)
+ specPbETag := computeETag(specPb)
+ specPbGzETag := computeETag(specPbGz)
+
+ lastModified := time.Now()
+
+ o.rwMutex.Lock()
+ defer o.rwMutex.Unlock()
+
+ o.specBytes = specBytes
+ o.specPb = specPb
+ o.specPbGz = specPbGz
+ o.specBytesETag = specBytesETag
+ o.specPbETag = specPbETag
+ o.specPbGzETag = specPbGzETag
+ o.lastModified = lastModified
+
+ return nil
+}
+
+func toProtoBinary(spec []byte) ([]byte, error) {
+ var info yaml.MapSlice
+ err := yaml.Unmarshal(spec, &info)
+ if err != nil {
+ return nil, err
+ }
+ document, err := openapi_v2.NewDocument(info, compiler.NewContext("$root", nil))
+ if err != nil {
+ return nil, err
+ }
+ return proto.Marshal(document)
+}
+
+func toGzip(data []byte) []byte {
+ var buf bytes.Buffer
+ zw := gzip.NewWriter(&buf)
+ zw.Write(data)
+ zw.Close()
+ return buf.Bytes()
+}
+
+// RegisterOpenAPIVersionedService registers a handler to provide access to provided swagger spec.
+func RegisterOpenAPIVersionedService(openapiSpec *spec.Swagger, servePath string, handler common.PathHandler) (*OpenAPIService, error) {
+ o := OpenAPIService{}
+ if err := o.UpdateSpec(openapiSpec); err != nil {
+ return nil, err
+ }
+
+ accepted := []struct {
+ Type string
+ SubType string
+ GetDataAndETag func() ([]byte, string, time.Time)
+ }{
+ {"application", "json", o.getSwaggerBytes},
+ {"application", "com.github.proto-openapi.spec.v2@v1.0+protobuf", o.getSwaggerPbBytes},
+ }
+
+ handler.Handle(servePath, gziphandler.GzipHandler(http.HandlerFunc(
+ func(w http.ResponseWriter, r *http.Request) {
+ decipherableFormats := r.Header.Get("Accept")
+ if decipherableFormats == "" {
+ decipherableFormats = "*/*"
+ }
+ clauses := goautoneg.ParseAccept(decipherableFormats)
+ w.Header().Add("Vary", "Accept")
+ for _, clause := range clauses {
+ for _, accepts := range accepted {
+ if clause.Type != accepts.Type && clause.Type != "*" {
+ continue
+ }
+ if clause.SubType != accepts.SubType && clause.SubType != "*" {
+ continue
+ }
+
+ // serve the first matching media type in the sorted clause list
+ data, etag, lastModified := accepts.GetDataAndETag()
+ w.Header().Set("Etag", etag)
+ // ServeContent will take care of caching using eTag.
+ http.ServeContent(w, r, servePath, lastModified, bytes.NewReader(data))
+ return
+ }
+ }
+ // Return 406 for not acceptable format
+ w.WriteHeader(406)
+ return
+ }),
+ ))
+
+ return &o, nil
+}
+
+// BuildAndRegisterOpenAPIVersionedService builds the spec and registers a handler to provide access to it.
+// Use this method if your OpenAPI spec is static. If you want to update the spec, use BuildOpenAPISpec then RegisterOpenAPIVersionedService.
+func BuildAndRegisterOpenAPIVersionedService(servePath string, webServices []*restful.WebService, config *common.Config, handler common.PathHandler) (*OpenAPIService, error) {
+ spec, err := builder.BuildOpenAPISpec(webServices, config)
+ if err != nil {
+ return nil, err
+ }
+ return RegisterOpenAPIVersionedService(spec, servePath, handler)
+}
diff --git a/metrics-server/vendor/k8s.io/kube-openapi/pkg/util/proto/doc.go b/metrics-server/vendor/k8s.io/kube-openapi/pkg/util/proto/doc.go
new file mode 100644
index 0000000..11ed8a6
--- /dev/null
+++ b/metrics-server/vendor/k8s.io/kube-openapi/pkg/util/proto/doc.go
@@ -0,0 +1,19 @@
+/*
+Copyright 2017 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 proto is a collection of libraries for parsing and indexing the type definitions.
+// The openapi spec contains the object model definitions and extensions metadata.
+package proto
diff --git a/metrics-server/vendor/k8s.io/kube-openapi/pkg/util/proto/document.go b/metrics-server/vendor/k8s.io/kube-openapi/pkg/util/proto/document.go
new file mode 100644
index 0000000..a57dcd3
--- /dev/null
+++ b/metrics-server/vendor/k8s.io/kube-openapi/pkg/util/proto/document.go
@@ -0,0 +1,299 @@
+/*
+Copyright 2017 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 proto
+
+import (
+ "fmt"
+ "sort"
+ "strings"
+
+ "github.com/googleapis/gnostic/OpenAPIv2"
+ "gopkg.in/yaml.v2"
+)
+
+func newSchemaError(path *Path, format string, a ...interface{}) error {
+ err := fmt.Sprintf(format, a...)
+ if path.Len() == 0 {
+ return fmt.Errorf("SchemaError: %v", err)
+ }
+ return fmt.Errorf("SchemaError(%v): %v", path, err)
+}
+
+// VendorExtensionToMap converts openapi VendorExtension to a map.
+func VendorExtensionToMap(e []*openapi_v2.NamedAny) map[string]interface{} {
+ values := map[string]interface{}{}
+
+ for _, na := range e {
+ if na.GetName() == "" || na.GetValue() == nil {
+ continue
+ }
+ if na.GetValue().GetYaml() == "" {
+ continue
+ }
+ var value interface{}
+ err := yaml.Unmarshal([]byte(na.GetValue().GetYaml()), &value)
+ if err != nil {
+ continue
+ }
+
+ values[na.GetName()] = value
+ }
+
+ return values
+}
+
+// Definitions is an implementation of `Models`. It looks for
+// models in an openapi Schema.
+type Definitions struct {
+ models map[string]Schema
+}
+
+var _ Models = &Definitions{}
+
+// NewOpenAPIData creates a new `Models` out of the openapi document.
+func NewOpenAPIData(doc *openapi_v2.Document) (Models, error) {
+ definitions := Definitions{
+ models: map[string]Schema{},
+ }
+
+ // Save the list of all models first. This will allow us to
+ // validate that we don't have any dangling reference.
+ for _, namedSchema := range doc.GetDefinitions().GetAdditionalProperties() {
+ definitions.models[namedSchema.GetName()] = nil
+ }
+
+ // Now, parse each model. We can validate that references exists.
+ for _, namedSchema := range doc.GetDefinitions().GetAdditionalProperties() {
+ path := NewPath(namedSchema.GetName())
+ schema, err := definitions.ParseSchema(namedSchema.GetValue(), &path)
+ if err != nil {
+ return nil, err
+ }
+ definitions.models[namedSchema.GetName()] = schema
+ }
+
+ return &definitions, nil
+}
+
+// We believe the schema is a reference, verify that and returns a new
+// Schema
+func (d *Definitions) parseReference(s *openapi_v2.Schema, path *Path) (Schema, error) {
+ if len(s.GetProperties().GetAdditionalProperties()) > 0 {
+ return nil, newSchemaError(path, "unallowed embedded type definition")
+ }
+ if len(s.GetType().GetValue()) > 0 {
+ return nil, newSchemaError(path, "definition reference can't have a type")
+ }
+
+ if !strings.HasPrefix(s.GetXRef(), "#/definitions/") {
+ return nil, newSchemaError(path, "unallowed reference to non-definition %q", s.GetXRef())
+ }
+ reference := strings.TrimPrefix(s.GetXRef(), "#/definitions/")
+ if _, ok := d.models[reference]; !ok {
+ return nil, newSchemaError(path, "unknown model in reference: %q", reference)
+ }
+ return &Ref{
+ BaseSchema: d.parseBaseSchema(s, path),
+ reference: reference,
+ definitions: d,
+ }, nil
+}
+
+func (d *Definitions) parseBaseSchema(s *openapi_v2.Schema, path *Path) BaseSchema {
+ return BaseSchema{
+ Description: s.GetDescription(),
+ Extensions: VendorExtensionToMap(s.GetVendorExtension()),
+ Path: *path,
+ }
+}
+
+// We believe the schema is a map, verify and return a new schema
+func (d *Definitions) parseMap(s *openapi_v2.Schema, path *Path) (Schema, error) {
+ if len(s.GetType().GetValue()) != 0 && s.GetType().GetValue()[0] != object {
+ return nil, newSchemaError(path, "invalid object type")
+ }
+ var sub Schema
+ if s.GetAdditionalProperties().GetSchema() == nil {
+ sub = &Arbitrary{
+ BaseSchema: d.parseBaseSchema(s, path),
+ }
+ } else {
+ var err error
+ sub, err = d.ParseSchema(s.GetAdditionalProperties().GetSchema(), path)
+ if err != nil {
+ return nil, err
+ }
+ }
+ return &Map{
+ BaseSchema: d.parseBaseSchema(s, path),
+ SubType: sub,
+ }, nil
+}
+
+func (d *Definitions) parsePrimitive(s *openapi_v2.Schema, path *Path) (Schema, error) {
+ var t string
+ if len(s.GetType().GetValue()) > 1 {
+ return nil, newSchemaError(path, "primitive can't have more than 1 type")
+ }
+ if len(s.GetType().GetValue()) == 1 {
+ t = s.GetType().GetValue()[0]
+ }
+ switch t {
+ case String: // do nothing
+ case Number: // do nothing
+ case Integer: // do nothing
+ case Boolean: // do nothing
+ default:
+ return nil, newSchemaError(path, "Unknown primitive type: %q", t)
+ }
+ return &Primitive{
+ BaseSchema: d.parseBaseSchema(s, path),
+ Type: t,
+ Format: s.GetFormat(),
+ }, nil
+}
+
+func (d *Definitions) parseArray(s *openapi_v2.Schema, path *Path) (Schema, error) {
+ if len(s.GetType().GetValue()) != 1 {
+ return nil, newSchemaError(path, "array should have exactly one type")
+ }
+ if s.GetType().GetValue()[0] != array {
+ return nil, newSchemaError(path, `array should have type "array"`)
+ }
+ if len(s.GetItems().GetSchema()) != 1 {
+ return nil, newSchemaError(path, "array should have exactly one sub-item")
+ }
+ sub, err := d.ParseSchema(s.GetItems().GetSchema()[0], path)
+ if err != nil {
+ return nil, err
+ }
+ return &Array{
+ BaseSchema: d.parseBaseSchema(s, path),
+ SubType: sub,
+ }, nil
+}
+
+func (d *Definitions) parseKind(s *openapi_v2.Schema, path *Path) (Schema, error) {
+ if len(s.GetType().GetValue()) != 0 && s.GetType().GetValue()[0] != object {
+ return nil, newSchemaError(path, "invalid object type")
+ }
+ if s.GetProperties() == nil {
+ return nil, newSchemaError(path, "object doesn't have properties")
+ }
+
+ fields := map[string]Schema{}
+
+ for _, namedSchema := range s.GetProperties().GetAdditionalProperties() {
+ var err error
+ path := path.FieldPath(namedSchema.GetName())
+ fields[namedSchema.GetName()], err = d.ParseSchema(namedSchema.GetValue(), &path)
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ return &Kind{
+ BaseSchema: d.parseBaseSchema(s, path),
+ RequiredFields: s.GetRequired(),
+ Fields: fields,
+ }, nil
+}
+
+func (d *Definitions) parseArbitrary(s *openapi_v2.Schema, path *Path) (Schema, error) {
+ return &Arbitrary{
+ BaseSchema: d.parseBaseSchema(s, path),
+ }, nil
+}
+
+// ParseSchema creates a walkable Schema from an openapi schema. While
+// this function is public, it doesn't leak through the interface.
+func (d *Definitions) ParseSchema(s *openapi_v2.Schema, path *Path) (Schema, error) {
+ if s.GetXRef() != "" {
+ return d.parseReference(s, path)
+ }
+ objectTypes := s.GetType().GetValue()
+ switch len(objectTypes) {
+ case 0:
+ // in the OpenAPI schema served by older k8s versions, object definitions created from structs did not include
+ // the type:object property (they only included the "properties" property), so we need to handle this case
+ if s.GetProperties() != nil {
+ return d.parseKind(s, path)
+ } else {
+ // Definition has no type and no properties. Treat it as an arbitrary value
+ // TODO: what if it has additionalProperties or patternProperties?
+ return d.parseArbitrary(s, path)
+ }
+ case 1:
+ t := objectTypes[0]
+ switch t {
+ case object:
+ if s.GetProperties() != nil {
+ return d.parseKind(s, path)
+ } else {
+ return d.parseMap(s, path)
+ }
+ case array:
+ return d.parseArray(s, path)
+ }
+ return d.parsePrimitive(s, path)
+ default:
+ // the OpenAPI generator never generates (nor it ever did in the past) OpenAPI type definitions with multiple types
+ return nil, newSchemaError(path, "definitions with multiple types aren't supported")
+ }
+}
+
+// LookupModel is public through the interface of Models. It
+// returns a visitable schema from the given model name.
+func (d *Definitions) LookupModel(model string) Schema {
+ return d.models[model]
+}
+
+func (d *Definitions) ListModels() []string {
+ models := []string{}
+
+ for model := range d.models {
+ models = append(models, model)
+ }
+
+ sort.Strings(models)
+ return models
+}
+
+type Ref struct {
+ BaseSchema
+
+ reference string
+ definitions *Definitions
+}
+
+var _ Reference = &Ref{}
+
+func (r *Ref) Reference() string {
+ return r.reference
+}
+
+func (r *Ref) SubSchema() Schema {
+ return r.definitions.models[r.reference]
+}
+
+func (r *Ref) Accept(v SchemaVisitor) {
+ v.VisitReference(r)
+}
+
+func (r *Ref) GetName() string {
+ return fmt.Sprintf("Reference to %q", r.reference)
+}
diff --git a/metrics-server/vendor/k8s.io/kube-openapi/pkg/util/proto/openapi.go b/metrics-server/vendor/k8s.io/kube-openapi/pkg/util/proto/openapi.go
new file mode 100644
index 0000000..f26b5ef
--- /dev/null
+++ b/metrics-server/vendor/k8s.io/kube-openapi/pkg/util/proto/openapi.go
@@ -0,0 +1,276 @@
+/*
+Copyright 2017 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 proto
+
+import (
+ "fmt"
+ "sort"
+ "strings"
+)
+
+// Defines openapi types.
+const (
+ Integer = "integer"
+ Number = "number"
+ String = "string"
+ Boolean = "boolean"
+
+ // These types are private as they should never leak, and are
+ // represented by actual structs.
+ array = "array"
+ object = "object"
+)
+
+// Models interface describe a model provider. They can give you the
+// schema for a specific model.
+type Models interface {
+ LookupModel(string) Schema
+ ListModels() []string
+}
+
+// SchemaVisitor is an interface that you need to implement if you want
+// to "visit" an openapi schema. A dispatch on the Schema type will call
+// the appropriate function based on its actual type:
+// - Array is a list of one and only one given subtype
+// - Map is a map of string to one and only one given subtype
+// - Primitive can be string, integer, number and boolean.
+// - Kind is an object with specific fields mapping to specific types.
+// - Reference is a link to another definition.
+type SchemaVisitor interface {
+ VisitArray(*Array)
+ VisitMap(*Map)
+ VisitPrimitive(*Primitive)
+ VisitKind(*Kind)
+ VisitReference(Reference)
+}
+
+// SchemaVisitorArbitrary is an additional visitor interface which handles
+// arbitrary types. For backwards compatibility, it's a separate interface
+// which is checked for at runtime.
+type SchemaVisitorArbitrary interface {
+ SchemaVisitor
+ VisitArbitrary(*Arbitrary)
+}
+
+// Schema is the base definition of an openapi type.
+type Schema interface {
+ // Giving a visitor here will let you visit the actual type.
+ Accept(SchemaVisitor)
+
+ // Pretty print the name of the type.
+ GetName() string
+ // Describes how to access this field.
+ GetPath() *Path
+ // Describes the field.
+ GetDescription() string
+ // Returns type extensions.
+ GetExtensions() map[string]interface{}
+}
+
+// Path helps us keep track of type paths
+type Path struct {
+ parent *Path
+ key string
+}
+
+func NewPath(key string) Path {
+ return Path{key: key}
+}
+
+func (p *Path) Get() []string {
+ if p == nil {
+ return []string{}
+ }
+ if p.key == "" {
+ return p.parent.Get()
+ }
+ return append(p.parent.Get(), p.key)
+}
+
+func (p *Path) Len() int {
+ return len(p.Get())
+}
+
+func (p *Path) String() string {
+ return strings.Join(p.Get(), "")
+}
+
+// ArrayPath appends an array index and creates a new path
+func (p *Path) ArrayPath(i int) Path {
+ return Path{
+ parent: p,
+ key: fmt.Sprintf("[%d]", i),
+ }
+}
+
+// FieldPath appends a field name and creates a new path
+func (p *Path) FieldPath(field string) Path {
+ return Path{
+ parent: p,
+ key: fmt.Sprintf(".%s", field),
+ }
+}
+
+// BaseSchema holds data used by each types of schema.
+type BaseSchema struct {
+ Description string
+ Extensions map[string]interface{}
+
+ Path Path
+}
+
+func (b *BaseSchema) GetDescription() string {
+ return b.Description
+}
+
+func (b *BaseSchema) GetExtensions() map[string]interface{} {
+ return b.Extensions
+}
+
+func (b *BaseSchema) GetPath() *Path {
+ return &b.Path
+}
+
+// Array must have all its element of the same `SubType`.
+type Array struct {
+ BaseSchema
+
+ SubType Schema
+}
+
+var _ Schema = &Array{}
+
+func (a *Array) Accept(v SchemaVisitor) {
+ v.VisitArray(a)
+}
+
+func (a *Array) GetName() string {
+ return fmt.Sprintf("Array of %s", a.SubType.GetName())
+}
+
+// Kind is a complex object. It can have multiple different
+// subtypes for each field, as defined in the `Fields` field. Mandatory
+// fields are listed in `RequiredFields`. The key of the object is
+// always of type `string`.
+type Kind struct {
+ BaseSchema
+
+ // Lists names of required fields.
+ RequiredFields []string
+ // Maps field names to types.
+ Fields map[string]Schema
+}
+
+var _ Schema = &Kind{}
+
+func (k *Kind) Accept(v SchemaVisitor) {
+ v.VisitKind(k)
+}
+
+func (k *Kind) GetName() string {
+ properties := []string{}
+ for key := range k.Fields {
+ properties = append(properties, key)
+ }
+ return fmt.Sprintf("Kind(%v)", properties)
+}
+
+// IsRequired returns true if `field` is a required field for this type.
+func (k *Kind) IsRequired(field string) bool {
+ for _, f := range k.RequiredFields {
+ if f == field {
+ return true
+ }
+ }
+ return false
+}
+
+// Keys returns a alphabetically sorted list of keys.
+func (k *Kind) Keys() []string {
+ keys := make([]string, 0)
+ for key := range k.Fields {
+ keys = append(keys, key)
+ }
+ sort.Strings(keys)
+ return keys
+}
+
+// Map is an object who values must all be of the same `SubType`.
+// The key of the object is always of type `string`.
+type Map struct {
+ BaseSchema
+
+ SubType Schema
+}
+
+var _ Schema = &Map{}
+
+func (m *Map) Accept(v SchemaVisitor) {
+ v.VisitMap(m)
+}
+
+func (m *Map) GetName() string {
+ return fmt.Sprintf("Map of %s", m.SubType.GetName())
+}
+
+// Primitive is a literal. There can be multiple types of primitives,
+// and this subtype can be visited through the `subType` field.
+type Primitive struct {
+ BaseSchema
+
+ // Type of a primitive must be one of: integer, number, string, boolean.
+ Type string
+ Format string
+}
+
+var _ Schema = &Primitive{}
+
+func (p *Primitive) Accept(v SchemaVisitor) {
+ v.VisitPrimitive(p)
+}
+
+func (p *Primitive) GetName() string {
+ if p.Format == "" {
+ return p.Type
+ }
+ return fmt.Sprintf("%s (%s)", p.Type, p.Format)
+}
+
+// Arbitrary is a value of any type (primitive, object or array)
+type Arbitrary struct {
+ BaseSchema
+}
+
+var _ Schema = &Arbitrary{}
+
+func (a *Arbitrary) Accept(v SchemaVisitor) {
+ if visitor, ok := v.(SchemaVisitorArbitrary); ok {
+ visitor.VisitArbitrary(a)
+ }
+}
+
+func (a *Arbitrary) GetName() string {
+ return "Arbitrary value (primitive, object or array)"
+}
+
+// Reference implementation depends on the type of document.
+type Reference interface {
+ Schema
+
+ Reference() string
+ SubSchema() Schema
+}
diff --git a/metrics-server/vendor/k8s.io/kube-openapi/pkg/util/trie.go b/metrics-server/vendor/k8s.io/kube-openapi/pkg/util/trie.go
new file mode 100644
index 0000000..a9a76c1
--- /dev/null
+++ b/metrics-server/vendor/k8s.io/kube-openapi/pkg/util/trie.go
@@ -0,0 +1,79 @@
+/*
+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 util
+
+// A simple trie implementation with Add and HasPrefix methods only.
+type Trie struct {
+ children map[byte]*Trie
+ wordTail bool
+ word string
+}
+
+// NewTrie creates a Trie and add all strings in the provided list to it.
+func NewTrie(list []string) Trie {
+ ret := Trie{
+ children: make(map[byte]*Trie),
+ wordTail: false,
+ }
+ for _, v := range list {
+ ret.Add(v)
+ }
+ return ret
+}
+
+// Add adds a word to this trie
+func (t *Trie) Add(v string) {
+ root := t
+ for _, b := range []byte(v) {
+ child, exists := root.children[b]
+ if !exists {
+ child = &Trie{
+ children: make(map[byte]*Trie),
+ wordTail: false,
+ }
+ root.children[b] = child
+ }
+ root = child
+ }
+ root.wordTail = true
+ root.word = v
+}
+
+// HasPrefix returns true of v has any of the prefixes stored in this trie.
+func (t *Trie) HasPrefix(v string) bool {
+ _, has := t.GetPrefix(v)
+ return has
+}
+
+// GetPrefix is like HasPrefix but return the prefix in case of match or empty string otherwise.
+func (t *Trie) GetPrefix(v string) (string, bool) {
+ root := t
+ if root.wordTail {
+ return root.word, true
+ }
+ for _, b := range []byte(v) {
+ child, exists := root.children[b]
+ if !exists {
+ return "", false
+ }
+ if child.wordTail {
+ return child.word, true
+ }
+ root = child
+ }
+ return "", false
+}
diff --git a/metrics-server/vendor/k8s.io/kube-openapi/pkg/util/util.go b/metrics-server/vendor/k8s.io/kube-openapi/pkg/util/util.go
new file mode 100644
index 0000000..bcc0c4d
--- /dev/null
+++ b/metrics-server/vendor/k8s.io/kube-openapi/pkg/util/util.go
@@ -0,0 +1,39 @@
+/*
+Copyright 2017 The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package util
+
+import "strings"
+
+// ToCanonicalName converts Golang package/type name into canonical OpenAPI name.
+// Examples:
+// Input: k8s.io/api/core/v1.Pod
+// Output: io.k8s.api.core.v1.Pod
+//
+// Input: k8s.io/api/core/v1
+// Output: io.k8s.api.core.v1
+func ToCanonicalName(name string) string {
+ nameParts := strings.Split(name, "/")
+ // Reverse first part. e.g., io.k8s... instead of k8s.io...
+ if len(nameParts) > 0 && strings.Contains(nameParts[0], ".") {
+ parts := strings.Split(nameParts[0], ".")
+ for i, j := 0, len(parts)-1; i < j; i, j = i+1, j-1 {
+ parts[i], parts[j] = parts[j], parts[i]
+ }
+ nameParts[0] = strings.Join(parts, ".")
+ }
+ return strings.Join(nameParts, ".")
+}