feat: move web const to web api (#2737)

Signed-off-by: xuesongzuo@yunify.com <xuesongzuo@yunify.com>
This commit is contained in:
zuoxuesong-worker 2025-08-29 11:35:21 +08:00 committed by GitHub
parent 24c80637ac
commit c12ddbd092
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 71 additions and 95 deletions

View File

@ -1,55 +0,0 @@
package _const
import "k8s.io/apimachinery/pkg/runtime"
const (
// CoreAPIPath defines the base path for core API endpoints in the KubeKey API server.
// All core resource management routes (inventories, playbooks, etc.) are prefixed with this path.
CoreAPIPath = "/kapis/"
// SwaggerAPIPath defines the base path for serving the Swagger UI (OpenAPI documentation).
// This is used to provide interactive API documentation for the KubeKey API server.
SwaggerAPIPath = "/swagger-ui/"
// ResourcesAPIPath defines the base path for resource-related endpoints.
// This path is used as the prefix for routes that serve static resources, schemas, and related files.
ResourcesAPIPath = "/resources/"
// KubeKeyTag is the tag used for KubeKey related resources
// This tag is used to identify and categorize KubeKey-specific resources
// in the system, making it easier to filter and manage them
KubeKeyTag = "kubekey"
// OpenAPITag is the tag used for OpenAPI documentation
// This tag helps organize and identify OpenAPI/Swagger documentation
// related to the KubeKey API endpoints
OpenAPITag = "api"
// ResourceTag is the tag used for resource-related endpoints
// This tag helps organize and identify API endpoints that deal with
// resource management and operations
ResourceTag = "resources"
// StatusOK represents a successful operation status
// Used to indicate that an API operation completed successfully
// without any errors or issues
StatusOK = "ok"
)
// SUCCESS is a predefined successful result
// This is a convenience variable that provides a standard success response
// for API operations that don't need to return specific data
var SUCCESS = Result{Message: "success"}
// Result represents a generic API response with a message
// This type is used for simple API responses that only need to convey
// a status message, such as success or error notifications
type Result struct {
Message string `description:"error message" json:"message"`
}
// ListResult represents a paginated list response containing items and total count
// This type is used for API responses that return a list of items with pagination
// support, allowing clients to handle large datasets efficiently
type ListResult struct {
Items []runtime.Object `json:"items"` // The list of items in the current page
TotalItems int `json:"totalItems"` // The total number of items across all pages
}

View File

@ -40,6 +40,38 @@ const (
ResultPending = "pending"
)
const (
// CoreAPIPath defines the base path for core API endpoints in the KubeKey API server.
// All core resource management routes (inventories, playbooks, etc.) are prefixed with this path.
CoreAPIPath = "/kapis/"
// SwaggerAPIPath defines the base path for serving the Swagger UI (OpenAPI documentation).
// This is used to provide interactive API documentation for the KubeKey API server.
SwaggerAPIPath = "/swagger-ui/"
// ResourcesAPIPath defines the base path for resource-related endpoints.
// This path is used as the prefix for routes that serve static resources, schemas, and related files.
ResourcesAPIPath = "/resources/"
// KubeKeyTag is the tag used for KubeKey related resources
// This tag is used to identify and categorize KubeKey-specific resources
// in the system, making it easier to filter and manage them
KubeKeyTag = "kubekey"
// OpenAPITag is the tag used for OpenAPI documentation
// This tag helps organize and identify OpenAPI/Swagger documentation
// related to the KubeKey API endpoints
OpenAPITag = "api"
// ResourceTag is the tag used for resource-related endpoints
// This tag helps organize and identify API endpoints that deal with
// resource management and operations
ResourceTag = "resources"
// StatusOK represents a successful operation status
// Used to indicate that an API operation completed successfully
// without any errors or issues
StatusOK = "ok"
)
// SUCCESS is a global variable representing a successful operation result with a default success message.
// It can be used as a standard response for successful API calls.
var SUCCESS = Result{Message: ResultSucceed}

View File

@ -17,7 +17,6 @@ import (
ctrlclient "sigs.k8s.io/controller-runtime/pkg/client"
"github.com/kubesphere/kubekey/v4/config"
_const "github.com/kubesphere/kubekey/v4/pkg/const"
"github.com/kubesphere/kubekey/v4/pkg/web/api"
"github.com/kubesphere/kubekey/v4/pkg/web/handler"
"github.com/kubesphere/kubekey/v4/pkg/web/query"
@ -29,39 +28,39 @@ import (
func NewCoreService(workdir string, client ctrlclient.Client, restconfig *rest.Config) *restful.WebService {
ws := new(restful.WebService).
// the GroupVersion might be empty, we need to remove the final /
Path(strings.TrimRight(_const.CoreAPIPath+kkcorev1.SchemeGroupVersion.String(), "/"))
Path(strings.TrimRight(api.CoreAPIPath+kkcorev1.SchemeGroupVersion.String(), "/"))
inventoryHandler := handler.NewInventoryHandler(workdir, restconfig, client)
// Inventory management routes
ws.Route(ws.POST("/inventories").To(inventoryHandler.Post).
Metadata(restfulspec.KeyOpenAPITags, []string{_const.KubeKeyTag}).
Metadata(restfulspec.KeyOpenAPITags, []string{api.KubeKeyTag}).
Doc("create a inventory.").Operation("createInventory").
Consumes(restful.MIME_JSON).Produces(restful.MIME_JSON).
Reads(kkcorev1.Inventory{}).
Returns(http.StatusOK, _const.StatusOK, kkcorev1.Inventory{}))
Returns(http.StatusOK, api.StatusOK, kkcorev1.Inventory{}))
ws.Route(ws.PATCH("/namespaces/{namespace}/inventories/{inventory}").To(inventoryHandler.Patch).
Metadata(restfulspec.KeyOpenAPITags, []string{_const.KubeKeyTag}).
Metadata(restfulspec.KeyOpenAPITags, []string{api.KubeKeyTag}).
Doc("patch a inventory.").Operation("patchInventory").
Consumes(string(types.JSONPatchType), string(types.MergePatchType), string(types.ApplyPatchType)).Produces(restful.MIME_JSON).
Reads(kkcorev1.Inventory{}).
Param(ws.PathParameter("namespace", "the namespace of the inventory")).
Param(ws.PathParameter("inventory", "the name of the inventory")).
Param(ws.QueryParameter("promise", "promise to execute playbook").Required(false).DefaultValue("true")).
Returns(http.StatusOK, _const.StatusOK, kkcorev1.Inventory{}))
Returns(http.StatusOK, api.StatusOK, kkcorev1.Inventory{}))
ws.Route(ws.GET("/inventories").To(inventoryHandler.List).
Metadata(restfulspec.KeyOpenAPITags, []string{_const.KubeKeyTag}).
Metadata(restfulspec.KeyOpenAPITags, []string{api.KubeKeyTag}).
Doc("list all inventories.").Operation("listInventory").
Produces(restful.MIME_JSON).
Param(ws.QueryParameter(query.ParameterPage, "page").Required(false).DataFormat("page=%d")).
Param(ws.QueryParameter(query.ParameterLimit, "limit").Required(false)).
Param(ws.QueryParameter(query.ParameterAscending, "sort parameters, e.g. reverse=true").Required(false).DefaultValue("false")).
Param(ws.QueryParameter(query.ParameterOrderBy, "sort parameters, e.g. orderBy=createTime")).
Returns(http.StatusOK, _const.StatusOK, api.ListResult[kkcorev1.Inventory]{}))
Returns(http.StatusOK, api.StatusOK, api.ListResult[kkcorev1.Inventory]{}))
ws.Route(ws.GET("/namespaces/{namespace}/inventories").To(inventoryHandler.List).
Metadata(restfulspec.KeyOpenAPITags, []string{_const.KubeKeyTag}).
Metadata(restfulspec.KeyOpenAPITags, []string{api.KubeKeyTag}).
Doc("list all inventories in a namespace.").
Produces(restful.MIME_JSON).Operation("listInventoryInNamespace").
Param(ws.PathParameter("namespace", "the namespace of the inventory")).
@ -69,18 +68,18 @@ func NewCoreService(workdir string, client ctrlclient.Client, restconfig *rest.C
Param(ws.QueryParameter(query.ParameterLimit, "limit").Required(false)).
Param(ws.QueryParameter(query.ParameterAscending, "sort parameters, e.g. reverse=true").Required(false).DefaultValue("false")).
Param(ws.QueryParameter(query.ParameterOrderBy, "sort parameters, e.g. orderBy=createTime")).
Returns(http.StatusOK, _const.StatusOK, api.ListResult[kkcorev1.Inventory]{}))
Returns(http.StatusOK, api.StatusOK, api.ListResult[kkcorev1.Inventory]{}))
ws.Route(ws.GET("/namespaces/{namespace}/inventories/{inventory}").To(inventoryHandler.Info).
Metadata(restfulspec.KeyOpenAPITags, []string{_const.KubeKeyTag}).
Metadata(restfulspec.KeyOpenAPITags, []string{api.KubeKeyTag}).
Doc("get a inventory in a namespace.").Operation("getInventory").
Produces(restful.MIME_JSON).
Param(ws.PathParameter("namespace", "the namespace of the inventory")).
Param(ws.PathParameter("inventory", "the name of the inventory")).
Returns(http.StatusOK, _const.StatusOK, kkcorev1.Inventory{}))
Returns(http.StatusOK, api.StatusOK, kkcorev1.Inventory{}))
ws.Route(ws.GET("/namespaces/{namespace}/inventories/{inventory}/hosts").To(inventoryHandler.ListHosts).
Metadata(restfulspec.KeyOpenAPITags, []string{_const.KubeKeyTag}).
Metadata(restfulspec.KeyOpenAPITags, []string{api.KubeKeyTag}).
Doc("list all hosts in a inventory.").Operation("listInventoryHosts").
Produces(restful.MIME_JSON).
Param(ws.PathParameter("namespace", "the namespace of the inventory")).
@ -89,30 +88,30 @@ func NewCoreService(workdir string, client ctrlclient.Client, restconfig *rest.C
Param(ws.QueryParameter(query.ParameterLimit, "limit").Required(false)).
Param(ws.QueryParameter(query.ParameterAscending, "sort parameters, e.g. reverse=true").Required(false).DefaultValue("false")).
Param(ws.QueryParameter(query.ParameterOrderBy, "sort parameters, e.g. orderBy=createTime")).
Returns(http.StatusOK, _const.StatusOK, api.ListResult[api.InventoryHostTable]{}))
Returns(http.StatusOK, api.StatusOK, api.ListResult[api.InventoryHostTable]{}))
playbookHandler := handler.NewPlaybookHandler(workdir, restconfig, client)
// Playbook management routes
ws.Route(ws.POST("/playbooks").To(playbookHandler.Post).
Metadata(restfulspec.KeyOpenAPITags, []string{_const.KubeKeyTag}).
Metadata(restfulspec.KeyOpenAPITags, []string{api.KubeKeyTag}).
Doc("create a playbook.").Operation("createPlaybook").
Param(ws.QueryParameter("promise", "promise to execute playbook").Required(false).DefaultValue("true")).
Consumes(restful.MIME_JSON).Produces(restful.MIME_JSON).
Reads(kkcorev1.Playbook{}).
Returns(http.StatusOK, _const.StatusOK, kkcorev1.Playbook{}))
Returns(http.StatusOK, api.StatusOK, kkcorev1.Playbook{}))
ws.Route(ws.GET("/playbooks").To(playbookHandler.List).
Metadata(restfulspec.KeyOpenAPITags, []string{_const.KubeKeyTag}).
Metadata(restfulspec.KeyOpenAPITags, []string{api.KubeKeyTag}).
Doc("list all playbooks.").Operation("listPlaybook").
Produces(restful.MIME_JSON).
Param(ws.QueryParameter(query.ParameterPage, "page").Required(false).DataFormat("page=%d")).
Param(ws.QueryParameter(query.ParameterLimit, "limit").Required(false)).
Param(ws.QueryParameter(query.ParameterAscending, "sort parameters, e.g. reverse=true").Required(false).DefaultValue("false")).
Param(ws.QueryParameter(query.ParameterOrderBy, "sort parameters, e.g. orderBy=createTime")).
Returns(http.StatusOK, _const.StatusOK, api.ListResult[kkcorev1.Playbook]{}))
Returns(http.StatusOK, api.StatusOK, api.ListResult[kkcorev1.Playbook]{}))
ws.Route(ws.GET("/namespaces/{namespace}/playbooks").To(playbookHandler.List).
Metadata(restfulspec.KeyOpenAPITags, []string{_const.KubeKeyTag}).
Metadata(restfulspec.KeyOpenAPITags, []string{api.KubeKeyTag}).
Doc("list all playbooks in a namespace.").Operation("listPlaybookInNamespace").
Produces(restful.MIME_JSON).
Param(ws.PathParameter("namespace", "the namespace of the playbook")).
@ -120,32 +119,32 @@ func NewCoreService(workdir string, client ctrlclient.Client, restconfig *rest.C
Param(ws.QueryParameter(query.ParameterLimit, "limit").Required(false)).
Param(ws.QueryParameter(query.ParameterAscending, "sort parameters, e.g. reverse=true").Required(false).DefaultValue("false")).
Param(ws.QueryParameter(query.ParameterOrderBy, "sort parameters, e.g. orderBy=createTime")).
Returns(http.StatusOK, _const.StatusOK, api.ListResult[kkcorev1.Playbook]{}))
Returns(http.StatusOK, api.StatusOK, api.ListResult[kkcorev1.Playbook]{}))
ws.Route(ws.GET("/namespaces/{namespace}/playbooks/{playbook}").To(playbookHandler.Info).
Metadata(restfulspec.KeyOpenAPITags, []string{_const.KubeKeyTag}).
Metadata(restfulspec.KeyOpenAPITags, []string{api.KubeKeyTag}).
Doc("get or watch a playbook in a namespace.").Operation("getPlaybook").
Produces(restful.MIME_JSON).
Param(ws.PathParameter("namespace", "the namespace of the playbook")).
Param(ws.PathParameter("playbook", "the name of the playbook")).
Param(ws.QueryParameter("watch", "set to true to watch this playbook")).
Returns(http.StatusOK, _const.StatusOK, kkcorev1.Playbook{}))
Returns(http.StatusOK, api.StatusOK, kkcorev1.Playbook{}))
ws.Route(ws.GET("/namespaces/{namespace}/playbooks/{playbook}/log").To(playbookHandler.Log).
Metadata(restfulspec.KeyOpenAPITags, []string{_const.KubeKeyTag}).
Metadata(restfulspec.KeyOpenAPITags, []string{api.KubeKeyTag}).
Doc("get a playbook execute log.").Operation("getPlaybookLog").
Produces("text/plain").
Param(ws.PathParameter("namespace", "the namespace of the playbook")).
Param(ws.PathParameter("playbook", "the name of the playbook")).
Returns(http.StatusOK, _const.StatusOK, ""))
Returns(http.StatusOK, api.StatusOK, ""))
ws.Route(ws.DELETE("/namespaces/{namespace}/playbooks/{playbook}").To(playbookHandler.Delete).
Metadata(restfulspec.KeyOpenAPITags, []string{_const.KubeKeyTag}).
Metadata(restfulspec.KeyOpenAPITags, []string{api.KubeKeyTag}).
Doc("delete a playbook.").Operation("deletePlaybook").
Produces(restful.MIME_JSON).
Param(ws.PathParameter("namespace", "the namespace of the playbook")).
Param(ws.PathParameter("playbook", "the name of the playbook")).
Returns(http.StatusOK, _const.StatusOK, api.Result{}))
Returns(http.StatusOK, api.StatusOK, api.Result{}))
return ws
}
@ -155,44 +154,44 @@ func NewCoreService(workdir string, client ctrlclient.Client, restconfig *rest.C
// The {subpath:*} parameter allows for matching any path under /resources/schema/.
func NewSchemaService(rootPath string, workdir string, client ctrlclient.Client) *restful.WebService {
ws := new(restful.WebService)
ws.Path(strings.TrimRight(_const.ResourcesAPIPath, "/")).
ws.Path(strings.TrimRight(api.ResourcesAPIPath, "/")).
Produces(restful.MIME_JSON, "text/plain")
resourceHandler := handler.NewResourceHandler(rootPath, workdir, client)
ws.Route(ws.GET("/ip").To(resourceHandler.ListIP).
Doc("list available ip from ip cidr").
Metadata(restfulspec.KeyOpenAPITags, []string{_const.ResourceTag}).
Metadata(restfulspec.KeyOpenAPITags, []string{api.ResourceTag}).
Param(ws.QueryParameter("cidr", "the cidr for ip").Required(true)).
Param(ws.QueryParameter("sshPort", "the ssh port for ip").Required(false)).
Param(ws.QueryParameter(query.ParameterPage, "page").Required(false).DataFormat("page=%d")).
Param(ws.QueryParameter(query.ParameterLimit, "limit").Required(false)).
Param(ws.QueryParameter(query.ParameterAscending, "sort parameters, e.g. reverse=true").Required(false).DefaultValue("false")).
Param(ws.QueryParameter(query.ParameterOrderBy, "sort parameters, e.g. orderBy=ip").Required(false).DefaultValue("ip")).
Returns(http.StatusOK, _const.StatusOK, api.ListResult[api.IPTable]{}))
Returns(http.StatusOK, api.StatusOK, api.ListResult[api.IPTable]{}))
ws.Route(ws.GET("/schema/{subpath:*}").To(resourceHandler.SchemaInfo).
Metadata(restfulspec.KeyOpenAPITags, []string{_const.ResourceTag}))
Metadata(restfulspec.KeyOpenAPITags, []string{api.ResourceTag}))
ws.Route(ws.GET("/schema").To(resourceHandler.ListSchema).
Doc("list all schema as table").
Metadata(restfulspec.KeyOpenAPITags, []string{_const.ResourceTag}).
Metadata(restfulspec.KeyOpenAPITags, []string{api.ResourceTag}).
Param(ws.QueryParameter("cluster", "The namespace where the cluster resides").Required(false).DefaultValue("default")).
Param(ws.QueryParameter(query.ParameterPage, "page").Required(false).DataFormat("page=%d")).
Param(ws.QueryParameter(query.ParameterLimit, "limit").Required(false)).
Param(ws.QueryParameter(query.ParameterAscending, "sort parameters, e.g. reverse=true").Required(false).DefaultValue("false")).
Param(ws.QueryParameter(query.ParameterOrderBy, "sort parameters, e.g. orderBy=priority")).
Returns(http.StatusOK, _const.StatusOK, api.ListResult[api.SchemaTable]{}))
Returns(http.StatusOK, api.StatusOK, api.ListResult[api.SchemaTable]{}))
ws.Route(ws.POST("/schema/config").To(resourceHandler.PostConfig).
Doc("storing user-defined configuration information").
Reads(struct{}{}).
Param(ws.QueryParameter("cluster", "The namespace where the cluster resides").Required(false).DefaultValue("default")).
Param(ws.QueryParameter("inventory", "the inventory of the playbook").Required(false).DefaultValue("default")).
Metadata(restfulspec.KeyOpenAPITags, []string{_const.ResourceTag}))
Metadata(restfulspec.KeyOpenAPITags, []string{api.ResourceTag}))
ws.Route(ws.GET("/schema/config").To(resourceHandler.ConfigInfo).
Doc("get user-defined configuration information").
Metadata(restfulspec.KeyOpenAPITags, []string{_const.ResourceTag}))
Metadata(restfulspec.KeyOpenAPITags, []string{api.ResourceTag}))
return ws
}
@ -227,9 +226,9 @@ func NewUIService(path string) *restful.WebService {
requestedPath := req.PathParameter("subpath")
// If the path matches any API route, return 404 so other WebServices can handle it
if strings.HasPrefix(requestedPath, strings.TrimLeft(_const.CoreAPIPath, "/")) ||
strings.HasPrefix(requestedPath, strings.TrimLeft(_const.SwaggerAPIPath, "/")) ||
strings.HasPrefix(requestedPath, strings.TrimLeft(_const.ResourcesAPIPath, "/")) {
if strings.HasPrefix(requestedPath, strings.TrimLeft(api.CoreAPIPath, "/")) ||
strings.HasPrefix(requestedPath, strings.TrimLeft(api.SwaggerAPIPath, "/")) ||
strings.HasPrefix(requestedPath, strings.TrimLeft(api.ResourcesAPIPath, "/")) {
_ = resp.WriteError(http.StatusNotFound, errors.New("not found"))
return
}
@ -257,7 +256,7 @@ func NewUIService(path string) *restful.WebService {
// It mounts the embedded swagger-ui files and handles requests to display the API documentation
func NewSwaggerUIService() *restful.WebService {
ws := new(restful.WebService)
ws.Path(strings.TrimRight(_const.SwaggerAPIPath, "/"))
ws.Path(strings.TrimRight(api.SwaggerAPIPath, "/"))
subFS, err := fs.Sub(config.Swagger, "swagger-ui")
if err != nil {
@ -274,10 +273,10 @@ func NewSwaggerUIService() *restful.WebService {
}
resp.AddHeader("Content-Type", "text/html")
_, _ = resp.Write(data)
}).Metadata(restfulspec.KeyOpenAPITags, []string{_const.OpenAPITag}))
}).Metadata(restfulspec.KeyOpenAPITags, []string{api.OpenAPITag}))
ws.Route(ws.GET("/{subpath:*}").To(func(req *restful.Request, resp *restful.Response) {
fileServer.ServeHTTP(resp.ResponseWriter, req.Request)
}).Metadata(restfulspec.KeyOpenAPITags, []string{_const.OpenAPITag}))
}).Metadata(restfulspec.KeyOpenAPITags, []string{api.OpenAPITag}))
return ws
}