This is an automated email from the ASF dual-hosted git repository.

liujun pushed a commit to branch refactor-with-go
in repository https://gitbox.apache.org/repos/asf/dubbo-admin.git


The following commit(s) were added to refs/heads/refactor-with-go by this push:
     new ac48a33c add auto generate dubbo admin swagger (#1099)
ac48a33c is described below

commit ac48a33c14219afa5eb9078966e9816efa60ac5a
Author: Jun <[email protected]>
AuthorDate: Sun May 14 11:21:04 2023 +0800

    add auto generate dubbo admin swagger (#1099)
---
 Makefile                        |  13 +++
 cmd/admin/main.go               |   7 ++
 hack/swagger/README_ZH.md       |   9 ++
 hack/swagger/swagger.json       | 228 ++++++++++++++++++++++++++++++++++++++++
 pkg/admin/handlers/mock_rule.go |  60 +++++++++--
 pkg/admin/model/common.go       |  26 +++++
 pkg/admin/model/mock_rule.go    |   5 +
 7 files changed, 337 insertions(+), 11 deletions(-)

diff --git a/Makefile b/Makefile
index 5110b55b..eb091d2c 100644
--- a/Makefile
+++ b/Makefile
@@ -58,10 +58,12 @@ $(LOCALBIN):
 ## Tool Binaries
 KUSTOMIZE ?= $(LOCALBIN)/kustomize
 CONTROLLER_GEN ?= $(LOCALBIN)/controller-gen
+SWAGGER ?= $(LOCALBIN)/swag
 
 ## Tool Versions
 KUSTOMIZE_VERSION ?= v3.8.7
 CONTROLLER_TOOLS_VERSION ?= v0.10.0
+SWAGGER_VERSION ?= v1.16.1
 
 ## docker buildx support platform
 PLATFORMS ?= linux/arm64,linux/amd64
@@ -93,6 +95,11 @@ manifests: controller-gen ## Generate WebhookConfiguration, 
ClusterRole and Cust
 generate: controller-gen ## Generate code containing DeepCopy, DeepCopyInto, 
and DeepCopyObject method implementations.
        #$(CONTROLLER_GEN) object:headerFile="./hack/boilerplate.go.txt"  
crd:allowDangerousTypes=true paths="./..."
 
+.PHONY: dubbo-admin-swagger
+dubbo-admin-swagger: swagger-install ## Generate dubbo-admin swagger docs.
+       $(SWAGGER) init -d cmd/admin,pkg/admin -o hack/swagger
+       @rm -f hack/swagger/docs.go hack/swagger/swagger.yaml
+
 .PHONY: fmt
 fmt: ## Run go fmt against code.
        go fmt ./...
@@ -214,3 +221,9 @@ controller-gen: $(CONTROLLER_GEN) ## Download 
controller-gen locally if necessar
 $(CONTROLLER_GEN): $(LOCALBIN)
        test -s $(LOCALBIN)/controller-gen && $(LOCALBIN)/controller-gen 
--version | grep -q $(CONTROLLER_TOOLS_VERSION) || \
        GOBIN=$(LOCALBIN) go install 
sigs.k8s.io/controller-tools/cmd/controller-gen@$(CONTROLLER_TOOLS_VERSION)
+
+.PHONY: swagger-install
+swagger-install: $(SWAGGER) ## Download swagger locally if necessary.
+$(SWAGGER): $(LOCALBIN)
+       test -s $(LOCALBIN)/swag  || \
+       GOBIN=$(LOCALBIN) go install  
github.com/swaggo/swag/cmd/swag@$(SWAGGER_VERSION)
\ No newline at end of file
diff --git a/cmd/admin/main.go b/cmd/admin/main.go
index 72191b6d..0d83716a 100644
--- a/cmd/admin/main.go
+++ b/cmd/admin/main.go
@@ -23,6 +23,13 @@ import (
        "github.com/apache/dubbo-admin/pkg/admin/services"
 )
 
+// @title           Dubbo-Admin API
+// @version         1.0
+// @description     This is a dubbo-admin swagger ui server.
+// @license.name  Apache 2.0
+// @license.url   http://www.apache.org/licenses/LICENSE-2.0.html
+// @host      127.0.0.1:38080
+// @BasePath  /
 func main() {
        config.LoadConfig()
        go services.StartSubscribe(config.RegistryCenter)
diff --git a/hack/swagger/README_ZH.md b/hack/swagger/README_ZH.md
new file mode 100644
index 00000000..f6cb6e7b
--- /dev/null
+++ b/hack/swagger/README_ZH.md
@@ -0,0 +1,9 @@
+# swaggo 使用说明文档
+
+- 文档说明 https://github.com/swaggo/swag/blob/master/README_zh-CN.md
+- 样例代码 
https://github.com/swaggo/swag/blob/master/example/celler/controller/examples.go
+
+# 生成 dubbo-admin swagger 文档
+
+在项目根目录下执行 make dubbo-admin-swagger ,在 hack/swagger 目录下生成 swagger.json
+
diff --git a/hack/swagger/swagger.json b/hack/swagger/swagger.json
new file mode 100644
index 00000000..649248f5
--- /dev/null
+++ b/hack/swagger/swagger.json
@@ -0,0 +1,228 @@
+{
+    "swagger": "2.0",
+    "info": {
+        "description": "This is a dubbo-admin swagger ui server.",
+        "title": "Dubbo-Admin API",
+        "contact": {},
+        "license": {
+            "name": "Apache 2.0",
+            "url": "http://www.apache.org/licenses/LICENSE-2.0.html";
+        },
+        "version": "1.0"
+    },
+    "host": "127.0.0.1:38080",
+    "basePath": "/",
+    "paths": {
+        "/api/{env}/mock/rule": {
+            "post": {
+                "description": "Create or update MockRule",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "MockRules"
+                ],
+                "summary": "Create or update MockRule",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "default": "dev",
+                        "description": "environment",
+                        "name": "env",
+                        "in": "path"
+                    },
+                    {
+                        "description": "MockRule",
+                        "name": "mockRule",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "$ref": "#/definitions/model.MockRule"
+                        }
+                    }
+                ],
+                "responses": {
+                    "201": {
+                        "description": "Created",
+                        "schema": {
+                            "type": "boolean"
+                        }
+                    },
+                    "400": {
+                        "description": "Bad Request",
+                        "schema": {
+                            "$ref": "#/definitions/model.HTTPError"
+                        }
+                    },
+                    "500": {
+                        "description": "Internal Server Error",
+                        "schema": {
+                            "$ref": "#/definitions/model.HTTPError"
+                        }
+                    }
+                }
+            },
+            "delete": {
+                "description": "Delete MockRule by id",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "MockRules"
+                ],
+                "summary": "Delete MockRule by id",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "default": "dev",
+                        "description": "environment",
+                        "name": "env",
+                        "in": "path"
+                    },
+                    {
+                        "description": "MockRule",
+                        "name": "mockRule",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "$ref": "#/definitions/model.MockRule"
+                        }
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "OK",
+                        "schema": {
+                            "type": "boolean"
+                        }
+                    },
+                    "400": {
+                        "description": "Bad Request",
+                        "schema": {
+                            "$ref": "#/definitions/model.HTTPError"
+                        }
+                    },
+                    "500": {
+                        "description": "Internal Server Error",
+                        "schema": {
+                            "$ref": "#/definitions/model.HTTPError"
+                        }
+                    }
+                }
+            }
+        },
+        "/api/{env}/mock/rule/list": {
+            "get": {
+                "description": "Get MockRules by page",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "MockRules"
+                ],
+                "summary": "Get MockRules by page",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "default": "dev",
+                        "description": "environment",
+                        "name": "env",
+                        "in": "path"
+                    },
+                    {
+                        "type": "string",
+                        "description": "filter condition",
+                        "name": "filter",
+                        "in": "query"
+                    },
+                    {
+                        "type": "integer",
+                        "description": "page offset",
+                        "name": "offset",
+                        "in": "query"
+                    },
+                    {
+                        "type": "integer",
+                        "description": "page limit",
+                        "name": "limit",
+                        "in": "query"
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "OK",
+                        "schema": {
+                            "$ref": "#/definitions/model.ListMockRulesByPage"
+                        }
+                    },
+                    "400": {
+                        "description": "Bad Request",
+                        "schema": {
+                            "$ref": "#/definitions/model.HTTPError"
+                        }
+                    },
+                    "500": {
+                        "description": "Internal Server Error",
+                        "schema": {
+                            "$ref": "#/definitions/model.HTTPError"
+                        }
+                    }
+                }
+            }
+        }
+    },
+    "definitions": {
+        "model.HTTPError": {
+            "type": "object",
+            "properties": {
+                "error": {
+                    "description": "error message",
+                    "type": "string"
+                }
+            }
+        },
+        "model.ListMockRulesByPage": {
+            "type": "object",
+            "properties": {
+                "content": {
+                    "type": "array",
+                    "items": {
+                        "$ref": "#/definitions/model.MockRule"
+                    }
+                },
+                "total": {
+                    "type": "integer"
+                }
+            }
+        },
+        "model.MockRule": {
+            "type": "object",
+            "properties": {
+                "enable": {
+                    "type": "boolean"
+                },
+                "id": {
+                    "type": "integer"
+                },
+                "methodName": {
+                    "type": "string"
+                },
+                "rule": {
+                    "type": "string"
+                },
+                "serviceName": {
+                    "type": "string"
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/pkg/admin/handlers/mock_rule.go b/pkg/admin/handlers/mock_rule.go
index 27ad3a35..f0677e21 100644
--- a/pkg/admin/handlers/mock_rule.go
+++ b/pkg/admin/handlers/mock_rule.go
@@ -33,64 +33,102 @@ var mockRuleService services.MockRuleService = 
&services.MockRuleServiceImpl{
        Logger:         logger.Logger(),
 }
 
+// CreateOrUpdateMockRule godoc
+// @Summary      Create or update MockRule
+// @Description  Create or update MockRule
+// @Tags         MockRules
+// @Accept       json
+// @Produce      json
+// @Param        env       path  string          false  "environment"       
default(dev)
+// @Param        mockRule  body  model.MockRule  true   "MockRule"
+// @Success      201  {boolean} true
+// @Failure      400  {object}  model.HTTPError
+// @Failure      500  {object}  model.HTTPError
+// @Router       /api/{env}/mock/rule [post]
 func CreateOrUpdateMockRule(c *gin.Context) {
        var mockRule *model.MockRule
        if err := c.ShouldBindJSON(&mockRule); err != nil {
-               c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
+               c.JSON(http.StatusBadRequest, model.HTTPError{Error: 
err.Error()})
                return
        }
 
        if err := mockRuleService.CreateOrUpdateMockRule(mockRule); err != nil {
-               c.JSON(http.StatusInternalServerError, gin.H{"error": 
err.Error()})
+               c.JSON(http.StatusInternalServerError, model.HTTPError{Error: 
err.Error()})
                return
        }
 
        c.JSON(http.StatusCreated, true)
 }
 
+// DeleteMockRuleById godoc
+// @Summary      Delete MockRule by id
+// @Description  Delete MockRule by id
+// @Tags         MockRules
+// @Accept       json
+// @Produce      json
+// @Param        env      path  string          false  "environment"      
default(dev)
+// @Param        mockRule body  model.MockRule   true   "MockRule"
+// @Success      200  {boolean} true
+// @Failure      400  {object}  model.HTTPError
+// @Failure      500  {object}  model.HTTPError
+// @Router       /api/{env}/mock/rule [delete]
 func DeleteMockRuleById(c *gin.Context) {
        // TODO use c.Param("id") instead of http body
        // id, err := strconv.ParseInt(c.Param("id"), 10, 64)
 
        var mockRule *model.MockRule
        if err := c.ShouldBindJSON(&mockRule); err != nil {
-               c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
+               c.JSON(http.StatusBadRequest, model.HTTPError{Error: 
err.Error()})
                return
        }
        if mockRule.ID == 0 {
-               c.JSON(http.StatusBadRequest, gin.H{"error": "id is required"})
+               c.JSON(http.StatusBadRequest, model.HTTPError{Error: "id is 
required"})
                return
        }
        if err := mockRuleService.DeleteMockRuleById(int64(mockRule.ID)); err 
!= nil {
-               c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
+               c.JSON(http.StatusBadRequest, model.HTTPError{Error: 
err.Error()})
                return
        }
        c.JSON(http.StatusOK, true)
 }
 
+// ListMockRulesByPage godoc
+// @Summary      Get MockRules by page
+// @Description  Get MockRules by page
+// @Tags         MockRules
+// @Accept       json
+// @Produce      json
+// @Param        env       path      string  false  "environment"       
default(dev)
+// @Param        filter    query     string  false  "filter condition"
+// @Param        offset    query     int     false  "page offset"
+// @Param        limit     query     int     false  "page limit"
+// @Success      200  {object}  model.ListMockRulesByPage
+// @Failure      400  {object}  model.HTTPError
+// @Failure      500  {object}  model.HTTPError
+// @Router       /api/{env}/mock/rule/list [get]
 func ListMockRulesByPage(c *gin.Context) {
        filter := c.Query("filter")
        offset, err := strconv.Atoi(c.DefaultQuery("offset", "0"))
        if err != nil {
-               c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
+               c.JSON(http.StatusBadRequest, model.HTTPError{Error: 
err.Error()})
                return
        }
 
        limit, err := strconv.Atoi(c.DefaultQuery("limit", "-1"))
        if err != nil {
-               c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
+               c.JSON(http.StatusBadRequest, model.HTTPError{Error: 
err.Error()})
                return
        }
 
        mockRules, total, err := mockRuleService.ListMockRulesByPage(filter, 
offset, limit)
        if err != nil {
-               c.JSON(http.StatusInternalServerError, gin.H{"error": 
err.Error()})
+               c.JSON(http.StatusInternalServerError, model.HTTPError{Error: 
err.Error()})
                return
        }
 
        // FIXME: the response data is not compatible with the frontend
-       c.JSON(http.StatusOK, gin.H{
-               "total":   total,
-               "content": mockRules,
+       c.JSON(http.StatusOK, model.ListMockRulesByPage{
+               Total:   total,
+               Content: mockRules,
        })
 }
diff --git a/pkg/admin/model/common.go b/pkg/admin/model/common.go
new file mode 100644
index 00000000..0ea9dc47
--- /dev/null
+++ b/pkg/admin/model/common.go
@@ -0,0 +1,26 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements.  See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You 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 model
+
+type HTTPError struct {
+       // error message
+       Error string `json:"error"`
+}
+
+type ResponseAny struct {
+       Code int `json:"code"`
+       Data any `json:"data"`
+}
diff --git a/pkg/admin/model/mock_rule.go b/pkg/admin/model/mock_rule.go
index eaab05db..e27d0a0c 100644
--- a/pkg/admin/model/mock_rule.go
+++ b/pkg/admin/model/mock_rule.go
@@ -62,3 +62,8 @@ func (m *MockRuleEntity) ToMockRule() *MockRule {
 func (m *MockRuleEntity) TableName() string {
        return "mock_rule"
 }
+
+type ListMockRulesByPage struct {
+       Total   int64       `json:"total"`
+       Content []*MockRule `json:"content"`
+}

Reply via email to