mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-10-31 18:28:13 +00:00 
			
		
		
		
	Sort OpenAPI operation and path parameters
This commit is contained in:
		| @@ -183,8 +183,10 @@ func (o *openAPI) buildPaths() error { | |||||||
| 			for _, p := range inPathCommonParamsMap { | 			for _, p := range inPathCommonParamsMap { | ||||||
| 				pathItem.Parameters = append(pathItem.Parameters, p) | 				pathItem.Parameters = append(pathItem.Parameters, p) | ||||||
| 			} | 			} | ||||||
|  | 			sortParameters(pathItem.Parameters) | ||||||
| 			for _, route := range routes { | 			for _, route := range routes { | ||||||
| 				op, err := o.buildOperations(route, inPathCommonParamsMap) | 				op, err := o.buildOperations(route, inPathCommonParamsMap) | ||||||
|  | 				sortParameters(op.Parameters) | ||||||
| 				if err != nil { | 				if err != nil { | ||||||
| 					return err | 					return err | ||||||
| 				} | 				} | ||||||
| @@ -287,28 +289,6 @@ func (o *openAPI) buildResponse(model interface{}, description string) (spec.Res | |||||||
| 	}, nil | 	}, nil | ||||||
| } | } | ||||||
|  |  | ||||||
| func groupRoutesByPath(routes []restful.Route) (ret map[string][]restful.Route) { |  | ||||||
| 	ret = make(map[string][]restful.Route) |  | ||||||
| 	for _, r := range routes { |  | ||||||
| 		route, exists := ret[r.Path] |  | ||||||
| 		if !exists { |  | ||||||
| 			route = make([]restful.Route, 0, 1) |  | ||||||
| 		} |  | ||||||
| 		ret[r.Path] = append(route, r) |  | ||||||
| 	} |  | ||||||
| 	return ret |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func mapKeyFromParam(param *restful.Parameter) interface{} { |  | ||||||
| 	return struct { |  | ||||||
| 		Name string |  | ||||||
| 		Kind int |  | ||||||
| 	}{ |  | ||||||
| 		Name: param.Data().Name, |  | ||||||
| 		Kind: param.Data().Kind, |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (o *openAPI) findCommonParameters(routes []restful.Route) (map[interface{}]spec.Parameter, error) { | func (o *openAPI) findCommonParameters(routes []restful.Route) (map[interface{}]spec.Parameter, error) { | ||||||
| 	commonParamsMap := make(map[interface{}]spec.Parameter, 0) | 	commonParamsMap := make(map[interface{}]spec.Parameter, 0) | ||||||
| 	paramOpsCountByName := make(map[interface{}]int, 0) | 	paramOpsCountByName := make(map[interface{}]int, 0) | ||||||
| @@ -412,54 +392,3 @@ func (o *openAPI) buildParameters(restParam []*restful.Parameter) (ret []spec.Pa | |||||||
| 	} | 	} | ||||||
| 	return ret, nil | 	return ret, nil | ||||||
| } | } | ||||||
|  |  | ||||||
| // A simple trie implementation with Add an HasPrefix methods only. |  | ||||||
| type trie struct { |  | ||||||
| 	children map[byte]*trie |  | ||||||
| 	wordTail bool |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func createTrie(list []string) trie { |  | ||||||
| 	ret := trie{ |  | ||||||
| 		children: make(map[byte]*trie), |  | ||||||
| 		wordTail: false, |  | ||||||
| 	} |  | ||||||
| 	for _, v := range list { |  | ||||||
| 		ret.Add(v) |  | ||||||
| 	} |  | ||||||
| 	return ret |  | ||||||
| } |  | ||||||
|  |  | ||||||
| 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 |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (t *trie) HasPrefix(v string) bool { |  | ||||||
| 	root := t |  | ||||||
| 	if root.wordTail { |  | ||||||
| 		return true |  | ||||||
| 	} |  | ||||||
| 	for _, b := range []byte(v) { |  | ||||||
| 		child, exists := root.children[b] |  | ||||||
| 		if !exists { |  | ||||||
| 			return false |  | ||||||
| 		} |  | ||||||
| 		if child.wordTail { |  | ||||||
| 			return true |  | ||||||
| 		} |  | ||||||
| 		root = child |  | ||||||
| 	} |  | ||||||
| 	return false |  | ||||||
| } |  | ||||||
|   | |||||||
| @@ -25,7 +25,6 @@ import ( | |||||||
| 	"github.com/go-openapi/spec" | 	"github.com/go-openapi/spec" | ||||||
| 	"github.com/stretchr/testify/assert" | 	"github.com/stretchr/testify/assert" | ||||||
| 	"k8s.io/kubernetes/pkg/genericapiserver/openapi/common" | 	"k8s.io/kubernetes/pkg/genericapiserver/openapi/common" | ||||||
| 	"sort" |  | ||||||
| ) | ) | ||||||
|  |  | ||||||
| // setUp is a convenience function for setting up for (most) tests. | // setUp is a convenience function for setting up for (most) tests. | ||||||
| @@ -322,35 +321,6 @@ func getAdditionalTestParameters() []spec.Parameter { | |||||||
| 	return ret | 	return ret | ||||||
| } | } | ||||||
|  |  | ||||||
| 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] } |  | ||||||
|  |  | ||||||
| type ByName struct { |  | ||||||
| 	Parameters |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (s ByName) Less(i, j int) bool { |  | ||||||
| 	return s.Parameters[i].Name < s.Parameters[j].Name |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // TODO(mehdy): Consider sort parameters in actual spec generation for more predictable spec generation |  | ||||||
| func sortParameters(s *spec.Swagger) *spec.Swagger { |  | ||||||
| 	for k, p := range s.Paths.Paths { |  | ||||||
| 		sort.Sort(ByName{p.Parameters}) |  | ||||||
| 		sort.Sort(ByName{p.Get.Parameters}) |  | ||||||
| 		sort.Sort(ByName{p.Put.Parameters}) |  | ||||||
| 		sort.Sort(ByName{p.Post.Parameters}) |  | ||||||
| 		sort.Sort(ByName{p.Head.Parameters}) |  | ||||||
| 		sort.Sort(ByName{p.Delete.Parameters}) |  | ||||||
| 		sort.Sort(ByName{p.Options.Parameters}) |  | ||||||
| 		sort.Sort(ByName{p.Patch.Parameters}) |  | ||||||
| 		s.Paths.Paths[k] = p // Unnecessary?! Magic!!! |  | ||||||
| 	} |  | ||||||
| 	return s |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func getTestInputDefinition() spec.Schema { | func getTestInputDefinition() spec.Schema { | ||||||
| 	return spec.Schema{ | 	return spec.Schema{ | ||||||
| 		SchemaProps: spec.SchemaProps{ | 		SchemaProps: spec.SchemaProps{ | ||||||
| @@ -434,8 +404,6 @@ func TestBuildSwaggerSpec(t *testing.T) { | |||||||
| 	} | 	} | ||||||
| 	err := o.init() | 	err := o.init() | ||||||
| 	if assert.NoError(err) { | 	if assert.NoError(err) { | ||||||
| 		sortParameters(expected) |  | ||||||
| 		sortParameters(o.swagger) |  | ||||||
| 		assert.Equal(expected, o.swagger) | 		assert.Equal(expected, o.swagger) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										116
									
								
								pkg/genericapiserver/openapi/util.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										116
									
								
								pkg/genericapiserver/openapi/util.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,116 @@ | |||||||
|  | /* | ||||||
|  | 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 openapi | ||||||
|  |  | ||||||
|  | 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) (ret map[string][]restful.Route) { | ||||||
|  | 	ret = make(map[string][]restful.Route) | ||||||
|  | 	for _, r := range routes { | ||||||
|  | 		route, exists := ret[r.Path] | ||||||
|  | 		if !exists { | ||||||
|  | 			route = make([]restful.Route, 0, 1) | ||||||
|  | 		} | ||||||
|  | 		ret[r.Path] = append(route, r) | ||||||
|  | 	} | ||||||
|  | 	return ret | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func mapKeyFromParam(param *restful.Parameter) interface{} { | ||||||
|  | 	return struct { | ||||||
|  | 		Name string | ||||||
|  | 		Kind int | ||||||
|  | 	}{ | ||||||
|  | 		Name: param.Data().Name, | ||||||
|  | 		Kind: param.Data().Kind, | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // A simple trie implementation with Add an HasPrefix methods only. | ||||||
|  | type trie struct { | ||||||
|  | 	children map[byte]*trie | ||||||
|  | 	wordTail bool | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func createTrie(list []string) trie { | ||||||
|  | 	ret := trie{ | ||||||
|  | 		children: make(map[byte]*trie), | ||||||
|  | 		wordTail: false, | ||||||
|  | 	} | ||||||
|  | 	for _, v := range list { | ||||||
|  | 		ret.Add(v) | ||||||
|  | 	} | ||||||
|  | 	return ret | ||||||
|  | } | ||||||
|  |  | ||||||
|  | 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 | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (t *trie) HasPrefix(v string) bool { | ||||||
|  | 	root := t | ||||||
|  | 	if root.wordTail { | ||||||
|  | 		return true | ||||||
|  | 	} | ||||||
|  | 	for _, b := range []byte(v) { | ||||||
|  | 		child, exists := root.children[b] | ||||||
|  | 		if !exists { | ||||||
|  | 			return false | ||||||
|  | 		} | ||||||
|  | 		if child.wordTail { | ||||||
|  | 			return true | ||||||
|  | 		} | ||||||
|  | 		root = child | ||||||
|  | 	} | ||||||
|  | 	return false | ||||||
|  | } | ||||||
		Reference in New Issue
	
	Block a user
	 mbohlool
					mbohlool