Fix Swagger and API mismatch for action, trigger, rule list (#4982)

* Fix Swagger and API mismatch for action, trigger, rule list

* Add test case

Co-authored-by: ning.yougang <ning.yougang@navercorp.com>
diff --git a/core/controller/src/main/resources/apiv1swagger.json b/core/controller/src/main/resources/apiv1swagger.json
index 390ca38..33008ae 100644
--- a/core/controller/src/main/resources/apiv1swagger.json
+++ b/core/controller/src/main/resources/apiv1swagger.json
@@ -113,7 +113,7 @@
             "schema": {
               "type": "array",
               "items": {
-                "$ref": "#/definitions/Action"
+                "$ref": "#/definitions/ActionMeta"
               }
             }
           },
@@ -718,7 +718,7 @@
             "schema": {
               "type": "array",
               "items": {
-                "$ref": "#/definitions/Rule"
+                "$ref": "#/definitions/RuleMeta"
               }
             }
           },
@@ -1000,7 +1000,7 @@
             "schema": {
               "type": "array",
               "items": {
-                "$ref": "#/definitions/Trigger"
+                "$ref": "#/definitions/TriggerMeta"
               }
             }
           },
@@ -1889,6 +1889,54 @@
         }
       }
     },
+    "ActionMeta": {
+      "required": [
+        "namespace",
+        "name",
+        "version",
+        "publish",
+        "exec",
+        "limits"
+      ],
+      "properties": {
+        "namespace": {
+          "type": "string",
+          "description": "Namespace of the item",
+          "minLength": 1
+        },
+        "name": {
+          "type": "string",
+          "description": "Name of the item",
+          "minLength": 1
+        },
+        "version": {
+          "type": "string",
+          "description": "Semantic version of the item",
+          "minLength": 1
+        },
+        "publish": {
+          "type": "boolean",
+          "description": "Whether to publish the item or not"
+        },
+        "exec": {
+          "$ref": "#/definitions/ActionExecMeta"
+        },
+        "annotations": {
+          "type": "array",
+          "items": {
+            "$ref": "#/definitions/KeyValue"
+          },
+          "description": "annotations on the item"
+        },
+        "limits": {
+          "$ref": "#/definitions/ActionLimits"
+        },
+        "updated": {
+          "type": "integer",
+          "description": "Time when the action was updated"
+        }
+      }
+    },
     "ActionPut": {
       "description": "A restricted Action view used when updating an Action",
       "properties": {
@@ -2002,6 +2050,15 @@
       },
       "description": "definition of the action, such as javascript code or the name of a container"
     },
+    "ActionExecMeta": {
+      "properties": {
+        "binary": {
+          "type": "boolean",
+          "description": "Whether the action has a binary attachment or not. This attribute is ignored when creating or updating an action."
+        }
+      },
+      "description": "definition of the action, such as javascript code or the name of a container"
+    },
     "ActionPayload": {
       "required": [
         "payload"
@@ -2071,6 +2128,54 @@
         }
       }
     },
+    "RuleMeta": {
+      "required": [
+        "namespace",
+        "name",
+        "version",
+        "publish",
+        "trigger",
+        "action"
+      ],
+      "properties": {
+        "namespace": {
+          "type": "string",
+          "description": "Namespace of the item",
+          "minLength": 1
+        },
+        "name": {
+          "type": "string",
+          "description": "Name of the item",
+          "minLength": 1
+        },
+        "version": {
+          "type": "string",
+          "description": "Semantic version of the item",
+          "minLength": 1
+        },
+        "publish": {
+          "type": "boolean",
+          "description": "Whether to publish the item or not"
+        },
+        "annotations": {
+          "type": "array",
+          "items": {
+            "$ref": "#/definitions/KeyValue"
+          },
+          "description": "annotations on the item"
+        },
+        "updated": {
+          "type": "integer",
+          "description": "Time when the rule was updated"
+        },
+        "trigger": {
+          "$ref": "#/definitions/PathName"
+        },
+        "action": {
+          "$ref": "#/definitions/PathName"
+        }
+      }
+    },
     "RulePut": {
       "description": "A restricted Rule view used when updating a Rule",
       "properties": {
@@ -2170,6 +2275,46 @@
         }
       }
     },
+    "TriggerMeta": {
+      "required": [
+        "namespace",
+        "name",
+        "version",
+        "publish"
+      ],
+      "properties": {
+        "namespace": {
+          "type": "string",
+          "description": "Namespace of the item",
+          "minLength": 1
+        },
+        "name": {
+          "type": "string",
+          "description": "Name of the item",
+          "minLength": 1
+        },
+        "version": {
+          "type": "string",
+          "description": "Semantic version of the item",
+          "minLength": 1
+        },
+        "publish": {
+          "type": "boolean",
+          "description": "Whether to publish the item or not"
+        },
+        "annotations": {
+          "type": "array",
+          "items": {
+            "$ref": "#/definitions/KeyValue"
+          },
+          "description": "annotations on the item"
+        },
+        "updated": {
+          "type": "integer",
+          "description": "Time when the trigger was updated"
+        }
+      }
+    },
     "TriggerPut": {
       "description": "A restricted Trigger view used when updating the Trigger",
       "properties": {
diff --git a/tests/src/test/scala/system/rest/SwaggerTests.scala b/tests/src/test/scala/system/rest/SwaggerTests.scala
index ab0e317..a0422fe 100644
--- a/tests/src/test/scala/system/rest/SwaggerTests.scala
+++ b/tests/src/test/scala/system/rest/SwaggerTests.scala
@@ -46,6 +46,20 @@
     response.body().asString().contains("\"swagger\":") should be(true)
   }
 
+  it should "respond to /api-docs including ActionMeta/ActionExecMeta/RuleMeta/TriggerMeta" in {
+    val response = RestAssured.given().config(sslconfig).get(getServiceURL() + "/api/v1/api-docs")
+
+    response.statusCode() should be(200)
+    response.body().asString().contains("\"#/definitions/ActionMeta\"") should be(true)
+    response.body().asString().contains("\"#/definitions/ActionExecMeta\"") should be(true)
+    response.body().asString().contains("\"#/definitions/RuleMeta\"") should be(true)
+    response.body().asString().contains("\"#/definitions/TriggerMeta\"") should be(true)
+    response.body().asString().contains("\"ActionMeta\"") should be(true)
+    response.body().asString().contains("\"ActionExecMeta\"") should be(true)
+    response.body().asString().contains("\"RuleMeta\"") should be(true)
+    response.body().asString().contains("\"TriggerMeta\"") should be(true)
+  }
+
   it should "respond to invalid URI with status code 404" in {
     val auth = WhiskProperties.getBasicAuth
     val response =