fix: k8s dependency version: emicklei/go-restful

`emicklei/go-restful` is used by:
- `k8s.io/client-go`  (Godeps)

Refs:
- e121606b0d/Godeps/Godeps.json
This commit is contained in:
Fernandez Ludovic 2017-06-11 18:03:28 +02:00 committed by Ludovic Fernandez
parent a7297b49a4
commit 5aa017d9b5
26 changed files with 957 additions and 380 deletions

View file

@ -19,9 +19,35 @@ type SwaggerService struct {
}
func newSwaggerService(config Config) *SwaggerService {
return &SwaggerService{
sws := &SwaggerService{
config: config,
apiDeclarationMap: new(ApiDeclarationList)}
// Build all ApiDeclarations
for _, each := range config.WebServices {
rootPath := each.RootPath()
// skip the api service itself
if rootPath != config.ApiPath {
if rootPath == "" || rootPath == "/" {
// use routes
for _, route := range each.Routes() {
entry := staticPathFromRoute(route)
_, exists := sws.apiDeclarationMap.At(entry)
if !exists {
sws.apiDeclarationMap.Put(entry, sws.composeDeclaration(each, entry))
}
}
} else { // use root path
sws.apiDeclarationMap.Put(each.RootPath(), sws.composeDeclaration(each, each.RootPath()))
}
}
}
// if specified then call the PostBuilderHandler
if config.PostBuildHandler != nil {
config.PostBuildHandler(sws.apiDeclarationMap)
}
return sws
}
// LogInfo is the function that is called when this package needs to log. It defaults to log.Printf
@ -57,31 +83,6 @@ func RegisterSwaggerService(config Config, wsContainer *restful.Container) {
LogInfo("[restful/swagger] listing is available at %v%v", config.WebServicesUrl, config.ApiPath)
wsContainer.Add(ws)
// Build all ApiDeclarations
for _, each := range config.WebServices {
rootPath := each.RootPath()
// skip the api service itself
if rootPath != config.ApiPath {
if rootPath == "" || rootPath == "/" {
// use routes
for _, route := range each.Routes() {
entry := staticPathFromRoute(route)
_, exists := sws.apiDeclarationMap.At(entry)
if !exists {
sws.apiDeclarationMap.Put(entry, sws.composeDeclaration(each, entry))
}
}
} else { // use root path
sws.apiDeclarationMap.Put(each.RootPath(), sws.composeDeclaration(each, each.RootPath()))
}
}
}
// if specified then call the PostBuilderHandler
if config.PostBuildHandler != nil {
config.PostBuildHandler(sws.apiDeclarationMap)
}
// Check paths for UI serving
if config.StaticHandler == nil && config.SwaggerFilePath != "" && config.SwaggerPath != "" {
swaggerPathSlash := config.SwaggerPath
@ -138,7 +139,12 @@ func enableCORS(req *restful.Request, resp *restful.Response, chain *restful.Fil
}
func (sws SwaggerService) getListing(req *restful.Request, resp *restful.Response) {
listing := ResourceListing{SwaggerVersion: swaggerVersion, ApiVersion: sws.config.ApiVersion}
listing := sws.produceListing()
resp.WriteAsJson(listing)
}
func (sws SwaggerService) produceListing() ResourceListing {
listing := ResourceListing{SwaggerVersion: swaggerVersion, ApiVersion: sws.config.ApiVersion, Info: sws.config.Info}
sws.apiDeclarationMap.Do(func(k string, v ApiDeclaration) {
ref := Resource{Path: k}
if len(v.Apis) > 0 { // use description of first (could still be empty)
@ -146,11 +152,11 @@ func (sws SwaggerService) getListing(req *restful.Request, resp *restful.Respons
}
listing.Apis = append(listing.Apis, ref)
})
resp.WriteAsJson(listing)
return listing
}
func (sws SwaggerService) getDeclarations(req *restful.Request, resp *restful.Response) {
decl, ok := sws.apiDeclarationMap.At(composeRootPath(req))
decl, ok := sws.produceDeclarations(composeRootPath(req))
if !ok {
resp.WriteErrorString(http.StatusNotFound, "ApiDeclaration not found")
return
@ -180,11 +186,28 @@ func (sws SwaggerService) getDeclarations(req *restful.Request, resp *restful.Re
scheme = "https"
}
}
(&decl).BasePath = fmt.Sprintf("%s://%s", scheme, host)
decl.BasePath = fmt.Sprintf("%s://%s", scheme, host)
}
resp.WriteAsJson(decl)
}
func (sws SwaggerService) produceAllDeclarations() map[string]ApiDeclaration {
decls := map[string]ApiDeclaration{}
sws.apiDeclarationMap.Do(func(k string, v ApiDeclaration) {
decls[k] = v
})
return decls
}
func (sws SwaggerService) produceDeclarations(route string) (*ApiDeclaration, bool) {
decl, ok := sws.apiDeclarationMap.At(route)
if !ok {
return nil, false
}
decl.BasePath = sws.config.WebServicesUrl
return &decl, true
}
// composeDeclaration uses all routes and parameters to create a ApiDeclaration
func (sws SwaggerService) composeDeclaration(ws *restful.WebService, pathPrefix string) ApiDeclaration {
decl := ApiDeclaration{
@ -207,16 +230,18 @@ func (sws SwaggerService) composeDeclaration(ws *restful.WebService, pathPrefix
}
}
pathToRoutes.Do(func(path string, routes []restful.Route) {
api := Api{Path: strings.TrimSuffix(path, "/"), Description: ws.Documentation()}
api := Api{Path: strings.TrimSuffix(withoutWildcard(path), "/"), Description: ws.Documentation()}
voidString := "void"
for _, route := range routes {
operation := Operation{
Method: route.Method,
Summary: route.Doc,
Notes: route.Notes,
Type: asDataType(route.WriteSample),
Method: route.Method,
Summary: route.Doc,
Notes: route.Notes,
// Type gets overwritten if there is a write sample
DataTypeFields: DataTypeFields{Type: &voidString},
Parameters: []Parameter{},
Nickname: route.Operation,
ResponseMessages: composeResponseMessages(route, &decl)}
ResponseMessages: composeResponseMessages(route, &decl, &sws.config)}
operation.Consumes = route.Consumes
operation.Produces = route.Produces
@ -238,8 +263,15 @@ func (sws SwaggerService) composeDeclaration(ws *restful.WebService, pathPrefix
return decl
}
func withoutWildcard(path string) string {
if strings.HasSuffix(path, ":*}") {
return path[0:len(path)-3] + "}"
}
return path
}
// composeResponseMessages takes the ResponseErrors (if any) and creates ResponseMessages from them.
func composeResponseMessages(route restful.Route, decl *ApiDeclaration) (messages []ResponseMessage) {
func composeResponseMessages(route restful.Route, decl *ApiDeclaration, config *Config) (messages []ResponseMessage) {
if route.ResponseErrors == nil {
return messages
}
@ -262,7 +294,7 @@ func composeResponseMessages(route restful.Route, decl *ApiDeclaration) (message
if isCollection {
modelName = "array[" + modelName + "]"
}
modelBuilder{&decl.Models}.addModel(st, "")
modelBuilder{Models: &decl.Models, Config: config}.addModel(st, "")
// reference the model
message.ResponseModel = modelName
}
@ -299,23 +331,19 @@ func detectCollectionType(st reflect.Type) (bool, reflect.Type) {
// addModelFromSample creates and adds (or overwrites) a Model from a sample resource
func (sws SwaggerService) addModelFromSampleTo(operation *Operation, isResponse bool, sample interface{}, models *ModelList) {
st := reflect.TypeOf(sample)
isCollection, st := detectCollectionType(st)
modelName := modelBuilder{}.keyFrom(st)
if isResponse {
if isCollection {
modelName = "array[" + modelName + "]"
}
operation.Type = modelName
type_, items := asDataType(sample, &sws.config)
operation.Type = type_
operation.Items = items
}
modelBuilder{models}.addModelFrom(sample)
modelBuilder{Models: models, Config: &sws.config}.addModelFrom(sample)
}
func asSwaggerParameter(param restful.ParameterData) Parameter {
return Parameter{
DataTypeFields: DataTypeFields{
Type: &param.DataType,
Format: asFormat(param.DataType),
Format: asFormat(param.DataType, param.DataFormat),
DefaultValue: Special(param.DefaultValue),
},
Name: param.Name,
@ -360,7 +388,10 @@ func composeRootPath(req *restful.Request) string {
return path + "/" + g
}
func asFormat(name string) string {
func asFormat(dataType string, dataFormat string) string {
if dataFormat != "" {
return dataFormat
}
return "" // TODO
}
@ -380,9 +411,30 @@ func asParamType(kind int) string {
return ""
}
func asDataType(any interface{}) string {
if any == nil {
return "void"
func asDataType(any interface{}, config *Config) (*string, *Item) {
// If it's not a collection, return the suggested model name
st := reflect.TypeOf(any)
isCollection, st := detectCollectionType(st)
modelName := modelBuilder{}.keyFrom(st)
// if it's not a collection we are done
if !isCollection {
return &modelName, nil
}
return reflect.TypeOf(any).Name()
// XXX: This is not very elegant
// We create an Item object referring to the given model
models := ModelList{}
mb := modelBuilder{Models: &models, Config: config}
mb.addModelFrom(any)
elemTypeName := mb.getElementTypeName(modelName, "", st)
item := new(Item)
if mb.isPrimitiveType(elemTypeName) {
mapped := mb.jsonSchemaType(elemTypeName)
item.Type = &mapped
} else {
item.Ref = &elemTypeName
}
tmp := "array"
return &tmp, item
}