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

yuqi4733 pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/gravitino.git


The following commit(s) were added to refs/heads/main by this push:
     new 2f8ec3ecb [#4255] feat(docs): Add docs for Tag System (#4308)
2f8ec3ecb is described below

commit 2f8ec3ecb3f527448b920beea64c41a2bb977573
Author: Jerry Shao <[email protected]>
AuthorDate: Thu Aug 1 14:40:32 2024 +0800

    [#4255] feat(docs): Add docs for Tag System (#4308)
    
    ### What changes were proposed in this pull request?
    
    This PR proposes to add docs for tag system.
    
    ### Why are the changes needed?
    
    To let users know how to use tag system.
    
    Fix: #4255
    
    ### Does this PR introduce _any_ user-facing change?
    
    No.
    
    ### How was this patch tested?
    
    Manual test.
---
 docs/manage-fileset-metadata-using-gravitino.md |  14 +-
 docs/manage-tags-in-gravitino.md                | 343 +++++++++++++
 docs/open-api/openapi.yaml                      |  42 ++
 docs/open-api/tags.yaml                         | 614 ++++++++++++++++++++++++
 docs/open-api/topics.yaml                       |   1 -
 5 files changed, 1006 insertions(+), 8 deletions(-)

diff --git a/docs/manage-fileset-metadata-using-gravitino.md 
b/docs/manage-fileset-metadata-using-gravitino.md
index a2d7bbadb..22b12f5b1 100644
--- a/docs/manage-fileset-metadata-using-gravitino.md
+++ b/docs/manage-fileset-metadata-using-gravitino.md
@@ -389,13 +389,13 @@ fileset_new = 
catalog.as_fileset_catalog().alter_fileset(NameIdentifier.of("sche
 
 Currently, Gravitino supports the following changes to a fileset:
 
-| Supported modification             | JSON                                    
                     | Java                                          |
-|------------------------------------|--------------------------------------------------------------|-----------------------------------------------|
-| Rename a fileset                     | 
`{"@type":"rename","newName":"fileset_renamed"}`             | 
`FilesetChange.rename("fileset_renamed")`     |
-| Update a comment                     | 
`{"@type":"updateComment","newComment":"new_comment"}`       | 
`FilesetChange.updateComment("new_comment")`  |
-| Set a fileset property             | 
`{"@type":"setProperty","property":"key1","value":"value1"}` | 
`FilesetChange.setProperty("key1", "value1")` |
-| Remove a fileset property          | 
`{"@type":"removeProperty","property":"key1"}`               | 
`FilesetChange.removeProperty("key1")`        |
-| Remove comment                     | `{"@type":"removeComment"}`             
                     | `FilesetChange.removeComment()`               |
+| Supported modification     | JSON                                            
             | Java                                          |
+|----------------------------|--------------------------------------------------------------|-----------------------------------------------|
+| Rename a fileset           | 
`{"@type":"rename","newName":"fileset_renamed"}`             | 
`FilesetChange.rename("fileset_renamed")`     |
+| Update a comment           | 
`{"@type":"updateComment","newComment":"new_comment"}`       | 
`FilesetChange.updateComment("new_comment")`  |
+| Set a fileset property     | 
`{"@type":"setProperty","property":"key1","value":"value1"}` | 
`FilesetChange.setProperty("key1", "value1")` |
+| Remove a fileset property  | `{"@type":"removeProperty","property":"key1"}`  
             | `FilesetChange.removeProperty("key1")`        |
+| Remove comment             | `{"@type":"removeComment"}`                     
             | `FilesetChange.removeComment()`               |
 
 ### Drop a fileset
 
diff --git a/docs/manage-tags-in-gravitino.md b/docs/manage-tags-in-gravitino.md
new file mode 100644
index 000000000..0f04726df
--- /dev/null
+++ b/docs/manage-tags-in-gravitino.md
@@ -0,0 +1,343 @@
+---
+title: "Manage tags in Gravitino"
+slug: /manage-tags-in-gravitino
+date: 2024-07-24
+keyword: tag management, tag, tags, Gravitino
+license: This software is licensed under the Apache License version 2.
+---
+
+import Tabs from '@theme/Tabs';
+import TabItem from '@theme/TabItem';
+
+## Introduction
+
+Starting from 0.6.0, Gravitino introduces a new tag system that allows you to 
manage tags for
+metadata objects. Tags are a way to categorize and organize metadata objects 
in Gravitino.
+
+This document briefly introduces how to use tags in Gravitino by both 
Gravitino Java client and
+REST APIs. If you want to know more about the tag system in Gravitino, please 
refer to the
+Javadoc and REST API documentation.
+
+Note that current tag system is a basic implementation, some advanced features 
will be added in
+the future versions.
+
+:::info
+1. Metadata objects are objects that are managed in Gravitino, such as 
`CATALOG`, `SCHEMA`, `TABLE`,
+   `COLUMN`, `FILESET`, `TOPIC`, `COLUMN`, etc. A metadata object is combined 
by a `type` and a
+   comma-separated `name`. For example, a `CATAGLOG` object has a name 
"catalog1" with type
+   "CATALOG", a `SCHEMA` object has a name "catalog1.schema1" with type 
"SCHEMA", a `TABLE`
+   object has a name "catalog1.schema1.table1" with type "TABLE".
+2. Currently, only `CATALOG`, `SCHEMA`, `TABLE`, `FILESET`, `TOPIC` objects 
can be tagged, tagging
+   on `COLUMN` will be supported in the future.
+3. Tags in Gravitino is inheritable, so listing tags of a metadata object will 
also list the
+   tags of its parent metadata objects. For example, listing tags of a `Table` 
will also list
+   the tags of its parent `Schema` and `Catalog`.
+4. Same tag can be associated to both parent and child metadata objects. When 
you list the
+   associated tags of a child metadata object, this tag will be included twice 
in the result
+   list with different `inherited` values.
+:::
+
+## Tag operations
+
+### Create new tags
+
+The first step to manage tags is to create new tags. You can create a new tag 
by providing a tag
+name, optional comment and properties.
+
+<Tabs groupId='language' queryString>
+<TabItem value="shell" label="Shell">
+
+```shell
+curl -X POST -H "Accept: application/vnd.gravitino.v1+json" \
+-H "Content-Type: application/json" -d '{
+  "name": "tag1",
+  "comment": "This is a tag",
+  "properties": {
+    "key1": "value1",
+    "key2": "value2"
+  }
+}' http://localhost:8090/api/metalakes/test/tags
+```
+
+</TabItem>
+<TabItem value="java" label="Java">
+
+```java
+GravitinoClient client = ...
+Tag tag =
+    client.createTag("tag1", "This is a tag", ImmutableMap.of("key1", 
"value1", "key2", "value2"));
+```
+
+</TabItem>
+</Tabs>
+
+### List created tags
+
+You can list all the created tag names as well as tag objects in a metalake in 
Gravitino.
+
+<Tabs groupId='language' queryString>
+<TabItem value="shell" label="Shell">
+
+```shell
+curl -X GET -H "Accept: application/vnd.gravitino.v1+json" \
+http://localhost:8090/api/metalakes/test/tags
+
+curl -X GET -H "Accept: application/vnd.gravitino.v1+json" \
+http://localhost:8090/api/metalakes/test/tags?detailed=true
+```
+
+</TabItem>
+<TabItem value="java" label="Java">
+
+```java
+GravitinoClient client = ...
+String[] tagNames = client.listTags();
+
+Tag[] tags = client.listTagsInfo();
+```
+
+</TabItem>
+</Tabs>
+
+### Get a tag by name
+
+You can get a tag by its name.
+
+<Tabs groupId='language' queryString>
+<TabItem value="shell" label="Shell">
+
+```shell
+curl -X GET -H "Accept: application/vnd.gravitino.v1+json" \
+http://localhost:8090/api/metalakes/test/tags/tag1
+```
+
+</TabItem>
+<TabItem value="java" label="Java">
+
+```java
+GravitinoClient client = ...
+Tag tag = client.getTag("tag1");
+```
+
+</TabItem>
+</Tabs>
+
+### Update a tag
+
+Gravitino allows you to update a tag by providing a new tag name, comment and 
properties.
+
+<Tabs groupId='language' queryString>
+<TabItem value="shell" label="Shell">
+
+```shell
+curl -X PUT -H "Accept: application/vnd.gravitino.v1+json" \
+-H "Content-Type: application/json" -d '{
+  "updates": [
+    {
+      "@type": "rename",
+      "newName": "tag2"
+    },
+    {
+      "@type": "updateComment",
+      "newComment": "This is an updated tag"
+    },
+    {
+      "@type": "setProperty",
+      "property": "key3",
+      "value": "value3"
+    },
+    {
+      "@type": "removeProperty",
+      "property": "key1"
+    }
+  ]
+}' http://localhost:8090/api/metalakes/test/tags/tag1
+```
+
+</TabItem>
+<TabItem value="java" label="Java">
+
+```java
+GravitinoClient client = ...
+Tag tag = client.alterTag(
+    "tag1",
+    TagChange.rename("tag2"),
+    TagChange.updateComment("This is an updated tag"),
+    TagChange.setProperty("key3", "value3"),
+    TagChange.removeProperty("key1"));
+```
+
+</TabItem>
+</Tabs>
+
+Currently, Gravitino support the following tag changes:
+
+| Supported modification | JSON                                                
         | Java                                      |
+|------------------------|--------------------------------------------------------------|-------------------------------------------|
+| Rename a tag           | `{"@type":"rename","newName":"tag_renamed"}`        
         | `TagChange.rename("tag_renamed")`         |
+| Update a comment       | 
`{"@type":"updateComment","newComment":"new_comment"}`       | 
`TagChange.updateComment("new_comment")`  |
+| Set a tag property     | 
`{"@type":"setProperty","property":"key1","value":"value1"}` | 
`TagChange.setProperty("key1", "value1")` |
+| Remove a tag property  | `{"@type":"removeProperty","property":"key1"}`      
         | `TagChange.removeProperty("key1")`        |
+
+### Delete a tag
+
+You can delete a tag by its name.
+
+<Tabs groupId='language' queryString>
+<TabItem value="shell" label="Shell">
+
+```shell
+curl -X DELETE -H "Accept: application/vnd.gravitino.v1+json" \
+http://localhost:8090/api/metalakes/test/tags/tag2
+```
+
+</TabItem>
+<TabItem value="java" label="Java">
+
+```java
+GravitinoClient client = ...
+client.deleteTag("tag2");
+```
+
+</TabItem>
+</Tabs>
+
+## Tag associations
+
+Gravitino allows you to associate and disassociate tags with metadata objects. 
Currently, only
+`CATALOG`, `SCHEMA`, `TABLE`, `FILESET`, `TOPIC` objects can be tagged.
+
+### Associate and disassociate tags with a metadata object
+
+You can associate and disassociate tags with a metadata object by providing 
the object type, object
+name and tag names.
+
+The request path for REST API is 
`/api/metalakes/{metalake}/tags/{metadataObjectType}/{metadataObjectName}`.
+
+<Tabs groupId='language' queryString>
+<TabItem value="shell" label="Shell">
+
+```shell
+curl -X POST -H "Accept: application/vnd.gravitino.v1+json" \
+-H "Content-Type: application/json" -d '{
+  "tagsToAdd": ["tag1", "tag2"],
+  "tagsToRemove": ["tag3"]
+}' http://localhost:8090/api/metalakes/test/tags/catalog/catalog1
+
+curl -X POST -H "Accept: application/vnd.gravitino.v1+json" \
+-H "Content-Type: application/json" -d '{
+  "tagsToAdd": ["tag1"]
+}' http://localhost:8090/api/metalakes/test/tags/schema/catalog1.schema1
+```
+
+</TabItem>
+<TabItem value="java" label="Java">
+
+```java
+Catalog catalog1 = ...
+catalog1.supportsTags().associateTags(
+    new String[] {"tag1", "tag2"},
+    new String[] {"tag3"});
+
+Schema schema1 = ...
+schema1.supportsTags().associateTags(new String[] {"tag1"}, null);
+```
+
+</TabItem>
+</Tabs>
+
+### List associated tags for a metadata object
+
+You can list all the tags associated with a metadata object. The tags in 
Gravitino are
+inheritable, so listing tags of a metadata object will also list the tags of 
its parent metadata
+objects.
+
+The request path for REST API is 
`/api/metalakes/{metalake}/tags/{metadataObjectType}/{metadataObjectName}`.
+
+<Tabs groupId='language' queryString>
+<TabItem value="shell" label="Shell">
+
+```shell
+curl -X GET -H "Accept: application/vnd.gravitino.v1+json" \
+http://localhost:8090/api/metalakes/test/tags/catalog/catalog1
+
+curl -X GET -H "Accept: application/vnd.gravitino.v1+json" \
+http://localhost:8090/api/metalakes/test/tags/schema/catalog1.schema1
+
+curl -X GET -H "Accept: application/vnd.gravitino.v1+json" \
+http://localhost:8090/api/metalakes/test/tags/catalog/catalog1?details=true
+
+curl -X GET -H "Accept: application/vnd.gravitino.v1+json" \
+http://localhost:8090/api/metalakes/test/tags/schema/catalog1.schema1?details=true
+```
+
+</TabItem>
+<TabItem value="java" label="Java">
+
+```java
+Catalog catalog1 = ...
+String[] tags = catalog1.supportsTags().listTags();
+Tag[] tagsInfo = catalog1.supportsTags().listTagsInfo();
+
+Schema schema1 = ...
+String[] tags = schema1.supportsTags().listTags();
+Tag[] tagsInfo = schema1.supportsTags().listTagsInfo();
+```
+
+</TabItem>
+</Tabs>
+
+### Get an associated tag by name for a metadata object
+
+You can get an associated tag by its name for a metadata object.
+
+The request path for REST API is 
`/api/metalakes/{metalake}/tags/{metadataObjectType}/{metadataObjectName}/{tagName}`.
+
+<Tabs groupId='language' queryString>
+<TabItem value="shell" label="Shell">
+
+```shell
+curl -X GET -H "Accept: application/vnd.gravitino.v1+json" \
+http://localhost:8090/api/metalakes/test/tags/catalog/catalog1/tag1
+
+curl -X GET -H "Accept: application/vnd.gravitino.v1+json" \
+http://localhost:8090/api/metalakes/test/tags/schema/catalog1.schema1/tag1
+```
+
+</TabItem>
+<TabItem value="java" label="Java">
+
+```java
+Catalog catalog1 = ...
+Tag tag = catalog1.supportsTags().getTag("tag1");
+
+Schema schema1 = ...
+Tag tag = schema1.supportsTags().getTag("tag1");
+```
+
+</TabItem>
+</Tabs>
+
+### List metadata objects associated with a tag
+
+You can list all the metadata objects associated with a tag.
+
+<Tabs groupId='language' queryString>
+<TabItem value="shell" label="Shell">
+
+```shell
+curl -X GET -H "Accept: application/vnd.gravitino.v1+json" \
+http://localhost:8090/api/metalakes/test/tags/tag1/objects
+```
+
+</TabItem>
+<TabItem value="java" label="Java">
+
+```java
+Tag tag = ...
+MetadataObject[] objects = tag.associatedObjects().objects();
+int count = tag.associatedObjects().count();
+```
+
+</TabItem>
+</Tabs>
diff --git a/docs/open-api/openapi.yaml b/docs/open-api/openapi.yaml
index 9218a6b67..16eb47ff9 100644
--- a/docs/open-api/openapi.yaml
+++ b/docs/open-api/openapi.yaml
@@ -58,6 +58,18 @@ paths:
     # escape the path name by replacing `{ }` with `%7B %7D`
     $ref: "./metalakes.yaml#/paths/~1metalakes~1%7Bname%7D"
 
+  /metalakes/{metalake}/tags:
+    $ref: "./tags.yaml#/paths/~1metalakes~1%7Bmetalake%7D~1tags"
+
+  /metalakes/{metalake}/tags/{tag}:
+    $ref: "./tags.yaml#/paths/~1metalakes~1%7Bmetalake%7D~1tags~1%7Btag%7D"
+
+  /metalakes/{metalake}/tags/{metadataObjectType}/{metadataObjectFullName}:
+    $ref: 
"./tags.yaml#/paths/~1metalakes~1%7Bmetalake%7D~1tags~1%7BmetadataObjectType%7D~1%7BmetadataObjectFullName%7D"
+
+  
/metalakes/{metalake}/tags/{metadataObjectType}/{metadataObjectFullName}/{tag}:
+    $ref: 
"./tags.yaml#/paths/~1metalakes~1%7Bmetalake%7D~1tags~1%7BmetadataObjectType%7D~1%7BmetadataObjectFullName%7D~1%7Btag%7D"
+
   /metalakes/{metalake}/catalogs:
     $ref: "./catalogs.yaml#/paths/~1metalakes~1%7Bmetalake%7D~1catalogs"
 
@@ -291,6 +303,36 @@ components:
       schema:
         type: string
 
+    tag:
+      name: tag
+      in: path
+      description: The name of the tag
+      required: true
+      schema:
+        type: string
+
+    metadataObjectType:
+      name: metadataObjectType
+      in: path
+      description: The type of the metadata object
+      required: true
+      schema:
+        type: string
+        enum:
+          - "catalog"
+          - "schema"
+          - "table"
+          - "fileset"
+          - "topic"
+
+    metadataObjectFullName:
+      name: metadataObjectFullName
+      in: path
+      description: The full name of the metadata object
+      required: true
+      schema:
+        type: string
+
   securitySchemes:
 
     OAuth2WithJWT:
diff --git a/docs/open-api/tags.yaml b/docs/open-api/tags.yaml
new file mode 100644
index 000000000..51d211c09
--- /dev/null
+++ b/docs/open-api/tags.yaml
@@ -0,0 +1,614 @@
+#
+# 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.
+#
+
+---
+
+paths:
+
+  /metalakes/{metalake}/tags:
+    parameters:
+      - $ref: "./openapi.yaml#/components/parameters/metalake"
+    get:
+      tags:
+        - tag
+      summary: List tags (names)
+      operationId: listTags
+      parameters:
+        - $ref: "#/components/parameters/details"
+      responses:
+        "200":
+          description: Returns the list of tag objects if {details} is true, 
otherwise returns the list of tag name
+          content:
+            application/vnd.gravitino.v1+json:
+              schema:
+                oneOf:
+                  - $ref: "#/components/responses/NameListResponse"
+                  - $ref: "#/components/responses/TagListResponse"
+              examples:
+                NameListResponse:
+                  $ref: "#/components/examples/NameListResponse"
+                TagListResponse:
+                  $ref: "#/components/examples/TagListResponse"
+        "400":
+          $ref: "./openapi.yaml#/components/responses/BadRequestErrorResponse"
+        "404":
+          description: Not Found - The specified metalake does not exist
+          content:
+            application/vnd.gravitino.v1+json:
+              schema:
+                $ref: "./openapi.yaml#/components/schemas/ErrorModel"
+              examples:
+                NoSuchMetalakeException:
+                  $ref: 
"./metalakes.yaml#/components/examples/NoSuchMetalakeException"
+        "5xx":
+          $ref: "./openapi.yaml#/components/responses/ServerErrorResponse"
+
+    post:
+      tags:
+        - tag
+      summary: Create tag
+      operationId: createTag
+      requestBody:
+        content:
+          application/json:
+            schema:
+              $ref: "#/components/requests/TagCreateRequest"
+            examples:
+              TagCreate:
+                $ref: "#/components/examples/TagCreate"
+
+      responses:
+        "200":
+          description: Returns the created tag object
+          content:
+            application/vnd.gravitino.v1+json:
+              schema:
+                $ref: "#/components/responses/TagResponse"
+              examples:
+                TagResponse:
+                  $ref: "#/components/examples/TagResponse"
+        "409":
+          description: Conflict - The target tag already exists in the 
specified metalake
+          content:
+            application/vnd.gravitino.v1+json:
+              schema:
+                $ref: "./openapi.yaml#/components/schemas/ErrorModel"
+              examples:
+                TagAlreadyExistsException:
+                  $ref: "#/components/examples/TagAlreadyExistsException"
+        "5xx":
+          $ref: "./openapi.yaml#/components/responses/ServerErrorResponse"
+
+
+  /metalakes/{metalake}/tags/{tag}:
+    parameters:
+      - $ref: "./openapi.yaml#/components/parameters/metalake"
+      - $ref: "./openapi.yaml#/components/parameters/tag"
+
+    get:
+      tags:
+        - tag
+      summary: Get tag
+      operationId: getTag
+      description: Returns the specified tag information in the specified 
metalake
+      responses:
+        "200":
+          description: Returns the tag object
+          content:
+            application/vnd.gravitino.v1+json:
+              schema:
+                $ref: "#/components/responses/TagResponse"
+                examples:
+                  TagResponse:
+                    $ref: "#/components/examples/TagResponse"
+        "404":
+          description: Not Found - The specified tag does not exist in the 
specified metalake
+          content:
+            application/vnd.gravitino.v1+json:
+              schema:
+                $ref: "./openapi.yaml#/components/schemas/ErrorModel"
+              examples:
+                NoSuchMetalakeException:
+                  $ref: 
"./metalakes.yaml#/components/examples/NoSuchMetalakeException"
+                NoSuchTagException:
+                  $ref: "#/components/examples/NoSuchTagException"
+        "5xx":
+          $ref: "./openapi.yaml#/components/responses/ServerErrorResponse"
+
+    put:
+      tags:
+        - tag
+      summary: Update tag
+      operationId: alterTag
+      description: Alters the specified tag information in the specified 
metalake
+      requestBody:
+        content:
+          application/json:
+            schema:
+              $ref: "#/components/requests/TagUpdatesRequest"
+      responses:
+        "200":
+            description: Returns the updated tag object
+            content:
+              application/vnd.gravitino.v1+json:
+                schema:
+                  $ref: "#/components/responses/TagResponse"
+                examples:
+                  TagResponse:
+                    $ref: "#/components/examples/TagResponse"
+        "404":
+          description: Not Found - The specified tag does not exist in the 
specified metalake
+          content:
+            application/vnd.gravitino.v1+json:
+              schema:
+                $ref: "./openapi.yaml#/components/schemas/ErrorModel"
+              examples:
+                NoSuchMetalakeException:
+                  $ref: 
"./metalakes.yaml#/components/examples/NoSuchMetalakeException"
+                NoSuchTagException:
+                  $ref: "#/components/examples/NoSuchTagException"
+        "5xx":
+          $ref: "./openapi.yaml#/components/responses/ServerErrorResponse"
+
+    delete:
+      tags:
+        - tag
+      summary: Delete tag
+      operationId: deleteTag
+      responses:
+        "200":
+          $ref: "./openapi.yaml#/components/responses/DropResponse"
+        "400":
+          $ref: "./openapi.yaml#/components/responses/BadRequestErrorResponse"
+        "5xx":
+          $ref: "./openapi.yaml#/components/responses/ServerErrorResponse"
+
+
+  /metalakes/{metalake}/tags/{metadataObjectType}/{metadataObjectFullName}:
+    parameters:
+      - $ref: "./openapi.yaml#/components/parameters/metalake"
+      - $ref: "./openapi.yaml#/components/parameters/metadataObjectType"
+      - $ref: "./openapi.yaml#/components/parameters/metadataObjectFullName"
+    get:
+      tags:
+        - tag
+      summary: List tags (names) associated with the specified metadata object
+      operationId: listObjectTags
+      parameters:
+        - $ref: "#/components/parameters/details"
+      responses:
+        "200":
+          description: Returns the list of tag objects associated with 
specified metadata object if {details} is true, otherwise returns the list of 
tag name
+          content:
+            application/vnd.gravitino.v1+json:
+              schema:
+                oneOf:
+                  - $ref: "#/components/responses/NameListResponse"
+                  - $ref: "#/components/responses/TagListResponse"
+              examples:
+                NameListResponse:
+                  $ref: "#/components/examples/NameListResponse"
+                TagListResponse:
+                  $ref: "#/components/examples/TagListResponse"
+        "400":
+          $ref: "./openapi.yaml#/components/responses/BadRequestErrorResponse"
+        "5xx":
+          $ref: "./openapi.yaml#/components/responses/ServerErrorResponse"
+
+    post:
+      tags:
+        - tag
+      summary: Associate tags with the specified metadata object
+      operationId: associateTags
+      requestBody:
+        content:
+          application/json:
+            schema:
+              $ref: "#/components/requests/TagsAssociateRequest"
+            examples:
+              TagAssociate:
+                $ref: "#/components/examples/TagAssociate"
+      responses:
+        "200":
+          description: Returns the list of tag names associated with the 
specified metadata object
+          content:
+            application/vnd.gravitino.v1+json:
+              schema:
+                $ref: "#/components/responses/NameListResponse"
+              examples:
+                NameListResponse:
+                  $ref: "#/components/examples/NameListResponse"
+        "409":
+          description: Conflict - The target tag already associated with the 
specified metadata object
+          content:
+            application/vnd.gravitino.v1+json:
+              schema:
+                $ref: "./openapi.yaml#/components/schemas/ErrorModel"
+              examples:
+                TagAlreadyAssociatedException:
+                  $ref: "#/components/examples/TagAlreadyAssociatedException"
+        "5xx":
+          $ref: "./openapi.yaml#/components/responses/ServerErrorResponse"
+
+
+  
/metalakes/{metalake}/tags/{metadataObjectType}/{metadataObjectFullName}/{tag}:
+    parameters:
+      - $ref: "./openapi.yaml#/components/parameters/metalake"
+      - $ref: "./openapi.yaml#/components/parameters/metadataObjectType"
+      - $ref: "./openapi.yaml#/components/parameters/metadataObjectFullName"
+      - $ref: "./openapi.yaml#/components/parameters/tag"
+    get:
+      tags:
+        - tag
+      summary: get associated tag for metadata object with specified tag name
+      operationId: getObjectTag
+      parameters:
+        - $ref: "#/components/parameters/details"
+      responses:
+        "200":
+          description: Returns the list of tag objects associated with 
specified metadata object if {details} is true, otherwise returns the list of 
tag name
+          content:
+            application/vnd.gravitino.v1+json:
+              schema:
+                $ref: "#/components/responses/TagResponse"
+              examples:
+                TagResponse:
+                  $ref: "#/components/examples/TagResponse"
+        "400":
+          $ref: "./openapi.yaml#/components/responses/BadRequestErrorResponse"
+        "404":
+          description: Not Found - The specified metadata object does not 
exist or the specified tag is not associated with the specified metadata object
+          content:
+            application/vnd.gravitino.v1+json:
+              schema:
+                $ref: "./openapi.yaml#/components/schemas/ErrorModel"
+              examples:
+                NoSuchTagException:
+                  $ref: "#/components/examples/NoSuchTagException"
+        "5xx":
+          $ref: "./openapi.yaml#/components/responses/ServerErrorResponse"
+
+components:
+  parameters:
+    details:
+      name: details
+      in: query
+      description: Include detailed information about the tag
+      required: false
+      schema:
+        type: boolean
+        default: false
+
+  schemas:
+
+    Tag:
+      type: object
+      description: A tag
+      required:
+        - name
+        - audit
+      properties:
+        name:
+          type: string
+          description: The name of the tag
+        comment:
+          type: string
+          description: A comment about the tag
+          nullable: true
+        audit:
+          $ref: "./openapi.yaml#/components/schemas/Audit"
+        properties:
+          type: object
+          description: Configured string to string map of properties for the 
tag
+          default: { }
+          additionalProperties:
+            type: string
+        inherited:
+          type: boolean
+          description: Whether the tag is inherited from the parent metadata 
object
+          nullable: true
+
+
+  requests:
+
+    TagCreateRequest:
+      type: object
+      required:
+        - name
+      properties:
+        name:
+          type: string
+          description: The name of the tag
+        comment:
+          type: string
+          description: A comment for the tag
+          nullable: true
+        properties:
+          type: object
+          description: A map of properties for the tag
+          nullable: true
+          default: { }
+          additionalProperties:
+            type: string
+
+    TagUpdatesRequest:
+      type: object
+      required:
+        - updates
+      properties:
+        updates:
+          type: array
+          items:
+            $ref: "#/components/requests/TagUpdateRequest"
+
+    TagUpdateRequest:
+      oneOf:
+        - $ref: "#/components/requests/RenameTagRequest"
+        - $ref: "#/components/requests/UpdateTagCommentRequest"
+        - $ref: "#/components/requests/SetTagPropertyRequest"
+        - $ref: "#/components/requests/RemoveTagPropertyRequest"
+      discriminator:
+        propertyName: "@type"
+        mapping:
+          rename: "#/components/requests/RenameTagRequest"
+          updateComment: "#/components/requests/UpdateTagCommentRequest"
+          setProperty: "#/components/requests/SetTagPropertyRequest"
+          removeProperty: "#/components/requests/RemoveTagPropertyRequest"
+
+    RenameTagRequest:
+      type: object
+      required:
+        - "@type"
+        - newName
+      properties:
+        "@type":
+          type: string
+          enum:
+            - rename
+        newName:
+          type: string
+          description: The new name of the tag
+      example: {
+        "@type": "rename",
+        "newName": "my_tag_new"
+      }
+
+    UpdateTagCommentRequest:
+      type: object
+      required:
+        - "@type"
+        - newComment
+      properties:
+        "@type":
+          type: string
+          enum:
+            - updateComment
+        newComment:
+          type: string
+          description: The new comment of the tag
+      example: {
+        "@type": "updateComment",
+        "newComment": "This is my new tag comment"
+      }
+
+    SetTagPropertyRequest:
+      type: object
+      required:
+        - "@type"
+        - property
+        - value
+      properties:
+        "@type":
+          type: string
+          enum:
+            - setProperty
+        property:
+          type: string
+          description: The property to set
+        value:
+          type: string
+          description: The value to set
+      example: {
+        "@type": "setProperty",
+        "property": "key1",
+        "value": "value1"
+      }
+
+    RemoveTagPropertyRequest:
+      type: object
+      required:
+        - "@type"
+        - property
+      properties:
+        "@type":
+          type: string
+          enum:
+            - removeProperty
+        property:
+          type: string
+          description: The property to remove
+      example: {
+        "@type": "removeProperty",
+        "property": "key2"
+      }
+
+    TagsAssociateRequest:
+      type: object
+      properties:
+        tagsToAdd:
+          type: array
+          items:
+            type: string
+          description: The tags to add
+          nullable: true
+        tagsToRemove:
+          type: array
+          items:
+            type: string
+          description: The tags to remove
+          nullable: true
+
+  responses:
+
+    NameListResponse:
+      type: object
+      properties:
+        code:
+          type: integer
+          format: int32
+          description: Status code of the response
+          enum:
+            - 0
+        names:
+          type: array
+          items:
+            type: string
+
+    TagListResponse:
+      type: object
+      properties:
+        code:
+          type: integer
+          format: int32
+          description: Status code of the response
+          enum:
+            - 0
+        tags:
+          type: array
+          description: A list of tag objects
+          items:
+            $ref: "#/components/schemas/Tag"
+
+    TagResponse:
+      type: object
+      properties:
+        code:
+          type: integer
+          format: int32
+          description: Status code of the response
+          enum:
+            - 0
+        tag:
+          $ref: "#/components/schemas/Tag"
+
+  examples:
+    NameListResponse:
+      value: {
+        "code": 0,
+        "names": ["my_tag1", "my_tag2"]
+      }
+
+    TagListResponse:
+      value: {
+        "code": 0,
+        "tags": [
+          {
+            "name": "my_tag1",
+            "comment": "This is my tag1",
+            "properties": {
+              "key1": "value1",
+              "key2": "value2"
+            },
+            "audit": {
+              "creator": "gravitino",
+              "createTime": "2023-12-08T03:41:25.595Z"
+            },
+            "inherited": null
+          },
+          {
+            "name": "my_tag2",
+            "comment": "This is my tag2",
+            "properties": {
+              "key2": "value2"
+            },
+            "audit": {
+              "creator": "gravitino",
+              "createTime": "2023-12-08T06:41:25.595Z"
+            },
+            "inherited": null
+          }
+        ]
+      }
+
+    TagCreate:
+      value: {
+        "name": "my_tag1",
+        "comment": "This is my tag1",
+        "properties": {
+          "key1": "value1",
+          "key2": "value2"
+        }
+      }
+
+    TagAssociate:
+      value: {
+        "tagsToAdd": ["my_tag1", "my_tag2"],
+        "tagsToRemove": ["my_tag3"]
+      }
+
+    TagResponse:
+      value: {
+        "code": 0,
+        "tag": {
+          "name": "my_tag1",
+          "comment": "This is my tag1",
+          "properties": {
+            "key1": "value1",
+            "key2": "value2"
+          },
+          "audit": {
+            "creator": "gravitino",
+            "createTime": "2023-12-08T03:41:25.595Z"
+          },
+          "inherited": false
+        }
+      }
+
+    TagAlreadyExistsException:
+      value: {
+        "code": 1004,
+        "type": "TagAlreadyExistsException",
+        "message": "Failed to operate tag(s) [my_tag] operation [CREATE], 
reason [TagAlreadyExistsException]",
+        "stack": [
+          "org.apache.gravitino.exceptions.TagAlreadyExistsException: Gag 
my_tag already exists",
+          "..."
+        ]
+      }
+
+    TagAlreadyAssociatedException:
+      value: {
+        "code": 1004,
+        "type": "TagAlreadyAssociatedException",
+        "message": "Failed to operate tag(s) [my_tag] operation [ASSOCIATE] 
under metalake [my_test_metalake], reason [TagAlreadyAssociatedException]",
+        "stack": [
+          "org.apache.gravitino.exceptions.TagAlreadyAssociatedException: Tag 
my_tag already associated",
+          "..."
+        ]
+      }
+
+    NoSuchTagException:
+      value: {
+        "code": 1003,
+        "type": "NoSuchTagException",
+        "message": "Failed to operate tag(s) [my_tag] operation [LOAD] under 
metalake [my_test_metalake], reason [NoSuchTagException]",
+        "stack": [
+          "org.apache.gravitino.exceptions.NoSuchTagException: Tag my_tag does 
not exist",
+          "..."
+        ]
+      }
diff --git a/docs/open-api/topics.yaml b/docs/open-api/topics.yaml
index ecfe91665..5469b56d2 100644
--- a/docs/open-api/topics.yaml
+++ b/docs/open-api/topics.yaml
@@ -15,7 +15,6 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-
 #
 
 ---


Reply via email to