Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ cd module/api
go run main.go --apiserver-host=https://192.168.33.129:6443
```

### Notice
If your API server is running with self-signed certificate, you can set `--apiserver-skip-tls-verify true` option to ignore the certificate verification.

### Frontend
Expand Down
81 changes: 49 additions & 32 deletions modules/api/pkg/handler/role.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,39 +26,56 @@ import (
"github.com/kubeedge/dashboard/errors"
)

// --- Routes registration using helper ---
// Replaces the original addRoleRoutes implementation
func (apiHandler *APIHandler) addRoleRoutes(apiV1Ws *restful.WebService) *APIHandler {
apiV1Ws.Route(
apiV1Ws.GET("/role").To(apiHandler.handleGetRoles).
Writes(rbacv1.RoleList{}).
Returns(http.StatusOK, "OK", rbacv1.RoleList{}))
apiV1Ws.Route(
apiV1Ws.GET("/role/{namespace}").To(apiHandler.handleGetRoles).
Param(apiV1Ws.PathParameter("namespace", "Name of the namespace")).
Writes(rbacv1.RoleList{}).
Returns(http.StatusOK, "OK", rbacv1.RoleList{}))
apiV1Ws.Route(
apiV1Ws.GET("/role/{namespace}/{name}").To(apiHandler.handleGetRole).
Param(apiV1Ws.PathParameter("namespace", "Name of the namespace")).
Param(apiV1Ws.PathParameter("name", "Name of the role")).
Writes(rbacv1.Role{}).
Returns(http.StatusOK, "OK", rbacv1.Role{}))
apiV1Ws.Route(
apiV1Ws.POST("/role/{namespace}").To(apiHandler.handleCreateRole).
Param(apiV1Ws.PathParameter("namespace", "Name of the namespace")).
Reads(rbacv1.Role{}).
Writes(rbacv1.Role{}).
Returns(http.StatusCreated, "Created", rbacv1.Role{}))
apiV1Ws.Route(
apiV1Ws.PUT("/role/{namespace}").To(apiHandler.handleUpdateRole).
Param(apiV1Ws.PathParameter("namespace", "Name of the namespace")).
Reads(rbacv1.Role{}).
Writes(rbacv1.Role{}).
Returns(http.StatusOK, "OK", rbacv1.Role{}))
apiV1Ws.Route(
apiV1Ws.DELETE("/role/{namespace}/{name}").To(apiHandler.handleDeleteRole).
Param(apiV1Ws.PathParameter("namespace", "Name of the namespace")).
Param(apiV1Ws.PathParameter("name", "Name of the role")).
Returns(http.StatusNoContent, "No Content", nil))
// Reusable path parameters (avoid recreating the same Parameter multiple times)
nsParam := apiV1Ws.PathParameter("namespace", "Name of the namespace")
nameParam := apiV1Ws.PathParameter("name", "Name of the role")

// GET /role -> list all roles (across namespaces)
AddRoute(apiV1Ws, http.MethodGet, "/role", apiHandler.handleGetRoles,
WithWrites(rbacv1.RoleList{}),
WithReturns(http.StatusOK, "OK", rbacv1.RoleList{}),
WithDoc("Get all roles"))

// GET /role/{namespace} -> list roles in a namespace
AddRoute(apiV1Ws, http.MethodGet, "/role/{namespace}", apiHandler.handleGetRoles,
WithParam(nsParam),
WithWrites(rbacv1.RoleList{}),
WithReturns(http.StatusOK, "OK", rbacv1.RoleList{}),
WithDoc("Get roles in a namespace"))

// GET /role/{namespace}/{name} -> get a specific role
AddRoute(apiV1Ws, http.MethodGet, "/role/{namespace}/{name}", apiHandler.handleGetRole,
WithParam(nsParam),
WithParam(nameParam),
WithWrites(rbacv1.Role{}),
WithReturns(http.StatusOK, "OK", rbacv1.Role{}),
WithDoc("Get a role by name"))

// POST /role/{namespace} -> create a new role
AddRoute(apiV1Ws, http.MethodPost, "/role/{namespace}", apiHandler.handleCreateRole,
WithParam(nsParam),
WithReads(rbacv1.Role{}),
WithWrites(rbacv1.Role{}),
WithReturns(http.StatusCreated, "Created", rbacv1.Role{}),
WithDoc("Create a role in a namespace"))

// PUT /role/{namespace} -> update a role (keep original path behavior)
AddRoute(apiV1Ws, http.MethodPut, "/role/{namespace}", apiHandler.handleUpdateRole,
WithParam(nsParam),
WithReads(rbacv1.Role{}),
WithWrites(rbacv1.Role{}),
WithReturns(http.StatusOK, "OK", rbacv1.Role{}),
WithDoc("Update a role in a namespace"))

// DELETE /role/{namespace}/{name} -> delete a role
AddRoute(apiV1Ws, http.MethodDelete, "/role/{namespace}/{name}", apiHandler.handleDeleteRole,
WithParam(nsParam),
WithParam(nameParam),
WithReturns(http.StatusNoContent, "No Content", nil),
WithDoc("Delete a role"))

return apiHandler
}
Expand Down
45 changes: 45 additions & 0 deletions modules/api/pkg/handler/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,3 +64,48 @@ func (apiHandler *APIHandler) getKubeEdgeClient(

return kubeEdgeClient, nil
}

// RouteOpt is a configuration function for RouteBuilder (similar to functional options).
type RouteOpt func(rb *restful.RouteBuilder)

// Common options: Param / Reads / Writes / Returns / Doc.
func WithParam(p *restful.Parameter) RouteOpt {
return func(rb *restful.RouteBuilder) {
rb.Param(p)
}
}

func WithReads(obj interface{}) RouteOpt {
return func(rb *restful.RouteBuilder) {
rb.Reads(obj)
}
}

func WithWrites(obj interface{}) RouteOpt {
return func(rb *restful.RouteBuilder) {
rb.Writes(obj)
}
}

func WithReturns(code int, desc string, obj interface{}) RouteOpt {
return func(rb *restful.RouteBuilder) {
rb.Returns(code, desc, obj)
}
}

func WithDoc(doc string) RouteOpt {
return func(rb *restful.RouteBuilder) {
rb.Doc(doc)
}
}

// AddRoute creates a RouteBuilder based on HTTP method, applies all RouteOpt,
// and registers it to the WebService.
func AddRoute(ws *restful.WebService, method string, path string, handler restful.RouteFunction, opts ...RouteOpt) {
rb := ws.Method(method).Path(path).To(handler)

for _, o := range opts {
o(rb)
}
ws.Route(rb)
}