mirror of https://github.com/k3s-io/k3s
Fix API Installer to generate unique Operation IDs
parent
e9f4db2748
commit
d228cc34f3
|
@ -47,10 +47,11 @@ type APIInstaller struct {
|
|||
|
||||
// Struct capturing information about an action ("GET", "POST", "WATCH", PROXY", etc).
|
||||
type action struct {
|
||||
Verb string // Verb identifying the action ("GET", "POST", "WATCH", PROXY", etc).
|
||||
Path string // The path of the action
|
||||
Params []*restful.Parameter // List of parameters associated with the action.
|
||||
Namer ScopeNamer
|
||||
Verb string // Verb identifying the action ("GET", "POST", "WATCH", PROXY", etc).
|
||||
Path string // The path of the action
|
||||
Params []*restful.Parameter // List of parameters associated with the action.
|
||||
Namer ScopeNamer
|
||||
AllNamespaces bool // true iff the action is namespaced but works on aggregate result for all namespaces
|
||||
}
|
||||
|
||||
// An interface to see if an object supports swagger documentation as a method
|
||||
|
@ -367,29 +368,29 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag
|
|||
|
||||
// Handler for standard REST verbs (GET, PUT, POST and DELETE).
|
||||
// Add actions at the resource path: /api/apiVersion/resource
|
||||
actions = appendIf(actions, action{"LIST", resourcePath, resourceParams, namer}, isLister)
|
||||
actions = appendIf(actions, action{"POST", resourcePath, resourceParams, namer}, isCreater)
|
||||
actions = appendIf(actions, action{"DELETECOLLECTION", resourcePath, resourceParams, namer}, isCollectionDeleter)
|
||||
actions = appendIf(actions, action{"LIST", resourcePath, resourceParams, namer, false}, isLister)
|
||||
actions = appendIf(actions, action{"POST", resourcePath, resourceParams, namer, false}, isCreater)
|
||||
actions = appendIf(actions, action{"DELETECOLLECTION", resourcePath, resourceParams, namer, false}, isCollectionDeleter)
|
||||
// DEPRECATED
|
||||
actions = appendIf(actions, action{"WATCHLIST", "watch/" + resourcePath, resourceParams, namer}, allowWatchList)
|
||||
actions = appendIf(actions, action{"WATCHLIST", "watch/" + resourcePath, resourceParams, namer, false}, allowWatchList)
|
||||
|
||||
// Add actions at the item path: /api/apiVersion/resource/{name}
|
||||
actions = appendIf(actions, action{"GET", itemPath, nameParams, namer}, isGetter)
|
||||
actions = appendIf(actions, action{"GET", itemPath, nameParams, namer, false}, isGetter)
|
||||
if getSubpath {
|
||||
actions = appendIf(actions, action{"GET", itemPath + "/{path:*}", proxyParams, namer}, isGetter)
|
||||
actions = appendIf(actions, action{"GET", itemPath + "/{path:*}", proxyParams, namer, false}, isGetter)
|
||||
}
|
||||
actions = appendIf(actions, action{"PUT", itemPath, nameParams, namer}, isUpdater)
|
||||
actions = appendIf(actions, action{"PATCH", itemPath, nameParams, namer}, isPatcher)
|
||||
actions = appendIf(actions, action{"DELETE", itemPath, nameParams, namer}, isDeleter)
|
||||
actions = appendIf(actions, action{"WATCH", "watch/" + itemPath, nameParams, namer}, isWatcher)
|
||||
actions = appendIf(actions, action{"PUT", itemPath, nameParams, namer, false}, isUpdater)
|
||||
actions = appendIf(actions, action{"PATCH", itemPath, nameParams, namer, false}, isPatcher)
|
||||
actions = appendIf(actions, action{"DELETE", itemPath, nameParams, namer, false}, isDeleter)
|
||||
actions = appendIf(actions, action{"WATCH", "watch/" + itemPath, nameParams, namer, false}, isWatcher)
|
||||
// We add "proxy" subresource to remove the need for the generic top level prefix proxy.
|
||||
// The generic top level prefix proxy is deprecated in v1.2, and will be removed in 1.3, or 1.4 at the latest.
|
||||
// TODO: DEPRECATED in v1.2.
|
||||
actions = appendIf(actions, action{"PROXY", "proxy/" + itemPath + "/{path:*}", proxyParams, namer}, isRedirector)
|
||||
actions = appendIf(actions, action{"PROXY", "proxy/" + itemPath + "/{path:*}", proxyParams, namer, false}, isRedirector)
|
||||
// TODO: DEPRECATED in v1.2.
|
||||
actions = appendIf(actions, action{"PROXY", "proxy/" + itemPath, nameParams, namer}, isRedirector)
|
||||
actions = appendIf(actions, action{"CONNECT", itemPath, nameParams, namer}, isConnecter)
|
||||
actions = appendIf(actions, action{"CONNECT", itemPath + "/{path:*}", proxyParams, namer}, isConnecter && connectSubpath)
|
||||
actions = appendIf(actions, action{"PROXY", "proxy/" + itemPath, nameParams, namer, false}, isRedirector)
|
||||
actions = appendIf(actions, action{"CONNECT", itemPath, nameParams, namer, false}, isConnecter)
|
||||
actions = appendIf(actions, action{"CONNECT", itemPath + "/{path:*}", proxyParams, namer, false}, isConnecter && connectSubpath)
|
||||
break
|
||||
case meta.RESTScopeNameNamespace:
|
||||
// Handler for standard REST verbs (GET, PUT, POST and DELETE).
|
||||
|
@ -420,36 +421,36 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag
|
|||
}
|
||||
namer := scopeNaming{scope, a.group.Linker, itemPathFn, false}
|
||||
|
||||
actions = appendIf(actions, action{"LIST", resourcePath, resourceParams, namer}, isLister)
|
||||
actions = appendIf(actions, action{"POST", resourcePath, resourceParams, namer}, isCreater)
|
||||
actions = appendIf(actions, action{"DELETECOLLECTION", resourcePath, resourceParams, namer}, isCollectionDeleter)
|
||||
actions = appendIf(actions, action{"LIST", resourcePath, resourceParams, namer, false}, isLister)
|
||||
actions = appendIf(actions, action{"POST", resourcePath, resourceParams, namer, false}, isCreater)
|
||||
actions = appendIf(actions, action{"DELETECOLLECTION", resourcePath, resourceParams, namer, false}, isCollectionDeleter)
|
||||
// DEPRECATED
|
||||
actions = appendIf(actions, action{"WATCHLIST", "watch/" + resourcePath, resourceParams, namer}, allowWatchList)
|
||||
actions = appendIf(actions, action{"WATCHLIST", "watch/" + resourcePath, resourceParams, namer, false}, allowWatchList)
|
||||
|
||||
actions = appendIf(actions, action{"GET", itemPath, nameParams, namer}, isGetter)
|
||||
actions = appendIf(actions, action{"GET", itemPath, nameParams, namer, false}, isGetter)
|
||||
if getSubpath {
|
||||
actions = appendIf(actions, action{"GET", itemPath + "/{path:*}", proxyParams, namer}, isGetter)
|
||||
actions = appendIf(actions, action{"GET", itemPath + "/{path:*}", proxyParams, namer, false}, isGetter)
|
||||
}
|
||||
actions = appendIf(actions, action{"PUT", itemPath, nameParams, namer}, isUpdater)
|
||||
actions = appendIf(actions, action{"PATCH", itemPath, nameParams, namer}, isPatcher)
|
||||
actions = appendIf(actions, action{"DELETE", itemPath, nameParams, namer}, isDeleter)
|
||||
actions = appendIf(actions, action{"WATCH", "watch/" + itemPath, nameParams, namer}, isWatcher)
|
||||
actions = appendIf(actions, action{"PUT", itemPath, nameParams, namer, false}, isUpdater)
|
||||
actions = appendIf(actions, action{"PATCH", itemPath, nameParams, namer, false}, isPatcher)
|
||||
actions = appendIf(actions, action{"DELETE", itemPath, nameParams, namer, false}, isDeleter)
|
||||
actions = appendIf(actions, action{"WATCH", "watch/" + itemPath, nameParams, namer, false}, isWatcher)
|
||||
// We add "proxy" subresource to remove the need for the generic top level prefix proxy.
|
||||
// The generic top level prefix proxy is deprecated in v1.2, and will be removed in 1.3, or 1.4 at the latest.
|
||||
// TODO: DEPRECATED in v1.2.
|
||||
actions = appendIf(actions, action{"PROXY", "proxy/" + itemPath + "/{path:*}", proxyParams, namer}, isRedirector)
|
||||
actions = appendIf(actions, action{"PROXY", "proxy/" + itemPath + "/{path:*}", proxyParams, namer, false}, isRedirector)
|
||||
// TODO: DEPRECATED in v1.2.
|
||||
actions = appendIf(actions, action{"PROXY", "proxy/" + itemPath, nameParams, namer}, isRedirector)
|
||||
actions = appendIf(actions, action{"CONNECT", itemPath, nameParams, namer}, isConnecter)
|
||||
actions = appendIf(actions, action{"CONNECT", itemPath + "/{path:*}", proxyParams, namer}, isConnecter && connectSubpath)
|
||||
actions = appendIf(actions, action{"PROXY", "proxy/" + itemPath, nameParams, namer, false}, isRedirector)
|
||||
actions = appendIf(actions, action{"CONNECT", itemPath, nameParams, namer, false}, isConnecter)
|
||||
actions = appendIf(actions, action{"CONNECT", itemPath + "/{path:*}", proxyParams, namer, false}, isConnecter && connectSubpath)
|
||||
|
||||
// list or post across namespace.
|
||||
// For ex: LIST all pods in all namespaces by sending a LIST request at /api/apiVersion/pods.
|
||||
// TODO: more strongly type whether a resource allows these actions on "all namespaces" (bulk delete)
|
||||
if !hasSubresource {
|
||||
namer = scopeNaming{scope, a.group.Linker, itemPathFn, true}
|
||||
actions = appendIf(actions, action{"LIST", resource, params, namer}, isLister)
|
||||
actions = appendIf(actions, action{"WATCHLIST", "watch/" + resource, params, namer}, allowWatchList)
|
||||
actions = appendIf(actions, action{"LIST", resource, params, namer, true}, isLister)
|
||||
actions = appendIf(actions, action{"WATCHLIST", "watch/" + resource, params, namer, true}, allowWatchList)
|
||||
}
|
||||
break
|
||||
default:
|
||||
|
@ -492,6 +493,15 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag
|
|||
if apiResource.Namespaced {
|
||||
namespaced = "Namespaced"
|
||||
}
|
||||
operationSuffix := ""
|
||||
if strings.HasSuffix(action.Path, "/{path:*}") {
|
||||
operationSuffix = operationSuffix + "WithPath"
|
||||
}
|
||||
if action.AllNamespaces {
|
||||
operationSuffix = operationSuffix + "ForAllNamespaces"
|
||||
namespaced = ""
|
||||
}
|
||||
|
||||
switch action.Verb {
|
||||
case "GET": // Get a resource.
|
||||
var handler restful.RouteFunction
|
||||
|
@ -508,7 +518,7 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag
|
|||
route := ws.GET(action.Path).To(handler).
|
||||
Doc(doc).
|
||||
Param(ws.QueryParameter("pretty", "If 'true', then the output is pretty printed.")).
|
||||
Operation("read"+namespaced+kind+strings.Title(subresource)).
|
||||
Operation("read"+namespaced+kind+strings.Title(subresource)+operationSuffix).
|
||||
Produces(append(storageMeta.ProducesMIMETypes(action.Verb), a.group.Serializer.SupportedMediaTypes()...)...).
|
||||
Returns(http.StatusOK, "OK", versionedObject).
|
||||
Writes(versionedObject)
|
||||
|
@ -533,7 +543,7 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag
|
|||
route := ws.GET(action.Path).To(handler).
|
||||
Doc(doc).
|
||||
Param(ws.QueryParameter("pretty", "If 'true', then the output is pretty printed.")).
|
||||
Operation("list"+namespaced+kind+strings.Title(subresource)).
|
||||
Operation("list"+namespaced+kind+strings.Title(subresource)+operationSuffix).
|
||||
Produces(append(storageMeta.ProducesMIMETypes(action.Verb), a.group.Serializer.SupportedMediaTypes()...)...).
|
||||
Returns(http.StatusOK, "OK", versionedList).
|
||||
Writes(versionedList)
|
||||
|
@ -565,7 +575,7 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag
|
|||
route := ws.PUT(action.Path).To(handler).
|
||||
Doc(doc).
|
||||
Param(ws.QueryParameter("pretty", "If 'true', then the output is pretty printed.")).
|
||||
Operation("replace"+namespaced+kind+strings.Title(subresource)).
|
||||
Operation("replace"+namespaced+kind+strings.Title(subresource)+operationSuffix).
|
||||
Produces(append(storageMeta.ProducesMIMETypes(action.Verb), a.group.Serializer.SupportedMediaTypes()...)...).
|
||||
Returns(http.StatusOK, "OK", versionedObject).
|
||||
Reads(versionedObject).
|
||||
|
@ -582,7 +592,7 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag
|
|||
Doc(doc).
|
||||
Param(ws.QueryParameter("pretty", "If 'true', then the output is pretty printed.")).
|
||||
Consumes(string(api.JSONPatchType), string(api.MergePatchType), string(api.StrategicMergePatchType)).
|
||||
Operation("patch"+namespaced+kind+strings.Title(subresource)).
|
||||
Operation("patch"+namespaced+kind+strings.Title(subresource)+operationSuffix).
|
||||
Produces(append(storageMeta.ProducesMIMETypes(action.Verb), a.group.Serializer.SupportedMediaTypes()...)...).
|
||||
Returns(http.StatusOK, "OK", versionedObject).
|
||||
Reads(unversioned.Patch{}).
|
||||
|
@ -604,7 +614,7 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag
|
|||
route := ws.POST(action.Path).To(handler).
|
||||
Doc(doc).
|
||||
Param(ws.QueryParameter("pretty", "If 'true', then the output is pretty printed.")).
|
||||
Operation("create"+namespaced+kind+strings.Title(subresource)).
|
||||
Operation("create"+namespaced+kind+strings.Title(subresource)+operationSuffix).
|
||||
Produces(append(storageMeta.ProducesMIMETypes(action.Verb), a.group.Serializer.SupportedMediaTypes()...)...).
|
||||
Returns(http.StatusOK, "OK", versionedObject).
|
||||
Reads(versionedObject).
|
||||
|
@ -620,7 +630,7 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag
|
|||
route := ws.DELETE(action.Path).To(handler).
|
||||
Doc(doc).
|
||||
Param(ws.QueryParameter("pretty", "If 'true', then the output is pretty printed.")).
|
||||
Operation("delete"+namespaced+kind+strings.Title(subresource)).
|
||||
Operation("delete"+namespaced+kind+strings.Title(subresource)+operationSuffix).
|
||||
Produces(append(storageMeta.ProducesMIMETypes(action.Verb), a.group.Serializer.SupportedMediaTypes()...)...).
|
||||
Writes(versionedStatus).
|
||||
Returns(http.StatusOK, "OK", versionedStatus)
|
||||
|
@ -638,7 +648,7 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag
|
|||
route := ws.DELETE(action.Path).To(handler).
|
||||
Doc(doc).
|
||||
Param(ws.QueryParameter("pretty", "If 'true', then the output is pretty printed.")).
|
||||
Operation("deletecollection"+namespaced+kind+strings.Title(subresource)).
|
||||
Operation("deletecollection"+namespaced+kind+strings.Title(subresource)+operationSuffix).
|
||||
Produces(append(storageMeta.ProducesMIMETypes(action.Verb), a.group.Serializer.SupportedMediaTypes()...)...).
|
||||
Writes(versionedStatus).
|
||||
Returns(http.StatusOK, "OK", versionedStatus)
|
||||
|
@ -657,7 +667,7 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag
|
|||
route := ws.GET(action.Path).To(handler).
|
||||
Doc(doc).
|
||||
Param(ws.QueryParameter("pretty", "If 'true', then the output is pretty printed.")).
|
||||
Operation("watch"+namespaced+kind+strings.Title(subresource)).
|
||||
Operation("watch"+namespaced+kind+strings.Title(subresource)+operationSuffix).
|
||||
Produces(a.group.Serializer.SupportedStreamingMediaTypes()...).
|
||||
Returns(http.StatusOK, "OK", versionedWatchEvent).
|
||||
Writes(versionedWatchEvent)
|
||||
|
@ -676,7 +686,7 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag
|
|||
route := ws.GET(action.Path).To(handler).
|
||||
Doc(doc).
|
||||
Param(ws.QueryParameter("pretty", "If 'true', then the output is pretty printed.")).
|
||||
Operation("watch"+namespaced+kind+strings.Title(subresource)+"List").
|
||||
Operation("watch"+namespaced+kind+strings.Title(subresource)+"List"+operationSuffix).
|
||||
Produces(a.group.Serializer.SupportedStreamingMediaTypes()...).
|
||||
Returns(http.StatusOK, "OK", versionedWatchEvent).
|
||||
Writes(versionedWatchEvent)
|
||||
|
@ -690,12 +700,12 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag
|
|||
// TODO: DEPRECATED in v1.2.
|
||||
case "PROXY": // Proxy requests to a resource.
|
||||
// Accept all methods as per http://issue.k8s.io/3996
|
||||
addProxyRoute(ws, "GET", a.prefix, action.Path, proxyHandler, namespaced, kind, resource, subresource, hasSubresource, action.Params)
|
||||
addProxyRoute(ws, "PUT", a.prefix, action.Path, proxyHandler, namespaced, kind, resource, subresource, hasSubresource, action.Params)
|
||||
addProxyRoute(ws, "POST", a.prefix, action.Path, proxyHandler, namespaced, kind, resource, subresource, hasSubresource, action.Params)
|
||||
addProxyRoute(ws, "DELETE", a.prefix, action.Path, proxyHandler, namespaced, kind, resource, subresource, hasSubresource, action.Params)
|
||||
addProxyRoute(ws, "HEAD", a.prefix, action.Path, proxyHandler, namespaced, kind, resource, subresource, hasSubresource, action.Params)
|
||||
addProxyRoute(ws, "OPTIONS", a.prefix, action.Path, proxyHandler, namespaced, kind, resource, subresource, hasSubresource, action.Params)
|
||||
addProxyRoute(ws, "GET", a.prefix, action.Path, proxyHandler, namespaced, kind, resource, subresource, hasSubresource, action.Params, operationSuffix)
|
||||
addProxyRoute(ws, "PUT", a.prefix, action.Path, proxyHandler, namespaced, kind, resource, subresource, hasSubresource, action.Params, operationSuffix)
|
||||
addProxyRoute(ws, "POST", a.prefix, action.Path, proxyHandler, namespaced, kind, resource, subresource, hasSubresource, action.Params, operationSuffix)
|
||||
addProxyRoute(ws, "DELETE", a.prefix, action.Path, proxyHandler, namespaced, kind, resource, subresource, hasSubresource, action.Params, operationSuffix)
|
||||
addProxyRoute(ws, "HEAD", a.prefix, action.Path, proxyHandler, namespaced, kind, resource, subresource, hasSubresource, action.Params, operationSuffix)
|
||||
addProxyRoute(ws, "OPTIONS", a.prefix, action.Path, proxyHandler, namespaced, kind, resource, subresource, hasSubresource, action.Params, operationSuffix)
|
||||
case "CONNECT":
|
||||
for _, method := range connecter.ConnectMethods() {
|
||||
doc := "connect " + method + " requests to " + kind
|
||||
|
@ -706,7 +716,7 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag
|
|||
route := ws.Method(method).Path(action.Path).
|
||||
To(handler).
|
||||
Doc(doc).
|
||||
Operation("connect" + strings.Title(strings.ToLower(method)) + namespaced + kind + strings.Title(subresource)).
|
||||
Operation("connect" + strings.Title(strings.ToLower(method)) + namespaced + kind + strings.Title(subresource) + operationSuffix).
|
||||
Produces("*/*").
|
||||
Consumes("*/*").
|
||||
Writes("string")
|
||||
|
@ -884,7 +894,7 @@ func routeFunction(handler http.Handler) restful.RouteFunction {
|
|||
}
|
||||
}
|
||||
|
||||
func addProxyRoute(ws *restful.WebService, method string, prefix string, path string, proxyHandler http.Handler, namespaced, kind, resource, subresource string, hasSubresource bool, params []*restful.Parameter) {
|
||||
func addProxyRoute(ws *restful.WebService, method string, prefix string, path string, proxyHandler http.Handler, namespaced, kind, resource, subresource string, hasSubresource bool, params []*restful.Parameter, operationSuffix string) {
|
||||
doc := "proxy " + method + " requests to " + kind
|
||||
if hasSubresource {
|
||||
doc = "proxy " + method + " requests to " + subresource + " of " + kind
|
||||
|
@ -892,7 +902,7 @@ func addProxyRoute(ws *restful.WebService, method string, prefix string, path st
|
|||
handler := metrics.InstrumentRouteFunc("PROXY", resource, routeFunction(proxyHandler))
|
||||
proxyRoute := ws.Method(method).Path(path).To(handler).
|
||||
Doc(doc).
|
||||
Operation("proxy" + strings.Title(method) + namespaced + kind + strings.Title(subresource)).
|
||||
Operation("proxy" + strings.Title(method) + namespaced + kind + strings.Title(subresource) + operationSuffix).
|
||||
Produces("*/*").
|
||||
Consumes("*/*").
|
||||
Writes("string")
|
||||
|
|
Loading…
Reference in New Issue