yuqi1129 commented on code in PR #11713:
URL: https://github.com/apache/gravitino/pull/11713#discussion_r3450541921


##########
docs/fileset-catalog-with-cos.md:
##########
@@ -0,0 +1,548 @@
+---
+title: "Fileset Catalog with COS"
+slug: "/fileset-catalog-with-cos"
+date: 2026-06-17
+keyword: "Fileset catalog COS Tencent"
+license: "This software is licensed under the Apache License version 2."
+---
+
+## Introduction
+
+This document explains how to configure a Fileset catalog with Tencent Cloud 
COS (Cloud Object Storage) in Gravitino.
+
+## Prerequisites
+
+To set up a Fileset catalog with COS, follow these steps:
+
+1. Download the 
[`gravitino-tencent-bundle-${gravitino-version}.jar`](https://mvnrepository.com/artifact/org.apache.gravitino/gravitino-tencent-bundle)
 file.
+2. Place the downloaded file into the Gravitino Fileset catalog classpath at 
`${GRAVITINO_HOME}/catalogs/fileset/libs/`.
+3. Start the Gravitino server by running the following command:
+
+```bash
+$ ${GRAVITINO_HOME}/bin/gravitino-server.sh start
+```
+
+Once the server is up and running, you can proceed to configure the Fileset 
catalog with COS. In the rest of this document we will use 
`http://localhost:8090` as the Gravitino server URL, replace with your actual 
server URL.
+
+## COS Catalog Configuration
+
+### COS Fileset Catalog Configuration
+
+In addition to the basic configurations mentioned in 
[Fileset-catalog-catalog-configuration](./fileset-catalog.md#catalog-properties),
 the following properties are required to configure a Fileset catalog with COS:
+
+| Configuration item            | Description                                  
                                                                                
                                                                                
                                                                                
                                                              | Default value | 
Required | Since version |
+|-------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------|----------|---------------|
+| `cos-region`                  | The region of the Tencent Cloud COS bucket, 
e.g. `ap-guangzhou`, `ap-shanghai`.                                             
                                                                                
                                                                                
                                                               | (none)        
| Yes      | 1.4.0         |
+| `cos-endpoint`                | The endpoint *suffix* of the Tencent Cloud 
COS service (mapped to `fs.cosn.bucket.endpoint_suffix`). It is a host suffix, 
not a full URL — e.g. `cos.ap-guangzhou.myqcloud.com`, **not** 
`https://cos.ap-guangzhou.myqcloud.com`. Optional; when not set, hadoop-cos 
derives it from `cos-region` (`cos.${region}.myqcloud.com`). Set this only if 
you need to point to a non-public endpoint (e.g. an internal/VPC endpoint).     
                                                                                
                           | (none)        | No       | 1.4.0         |
+| `cos-access-key-id`           | The static access key ID (Tencent Cloud 
`SecretId`) used to access COS data.                                            
                                                                                
                                                                                
                                                                   | (none)     
   | Yes      | 1.4.0         |
+| `cos-secret-access-key`       | The static secret access key (Tencent Cloud 
`SecretKey`) used to access COS data.                                           
                                                                                
                                                                                
                                                               | (none)        
| Yes      | 1.4.0         |
+| `credential-providers`        | The credential provider types, separated by 
comma. The currently supported value is `cos-secret-key`. Setting this enables 
credential vending provided by the Gravitino server, so the GVFS client no 
longer needs `cos-access-key-id` / `cos-secret-access-key` locally. See 
[cos-credential-vending](#fileset-with-credential-vending) below for details. | 
(none)        | No       | 1.4.0         |
+
+:::note
+The fileset catalog automatically loads filesystem providers on the classpath. 
The COS provider is registered when the `gravitino-tencent-bundle` jar is 
present, so `default-filesystem-provider` and `filesystem-providers` do not 
need to be set.
+:::
+
+:::note
+`cos-region` is mandatory for hadoop-cos: signing requests, building the 
default endpoint and selecting the right CAM scope all require the region. Even 
if you also set `cos-endpoint`, please keep `cos-region` set.

Review Comment:
   If possible, please just merge these two blocks



##########
docs/fileset-catalog-with-cos.md:
##########
@@ -0,0 +1,548 @@
+---
+title: "Fileset Catalog with COS"
+slug: "/fileset-catalog-with-cos"
+date: 2026-06-17
+keyword: "Fileset catalog COS Tencent"
+license: "This software is licensed under the Apache License version 2."
+---
+
+## Introduction
+
+This document explains how to configure a Fileset catalog with Tencent Cloud 
COS (Cloud Object Storage) in Gravitino.
+
+## Prerequisites
+
+To set up a Fileset catalog with COS, follow these steps:
+
+1. Download the 
[`gravitino-tencent-bundle-${gravitino-version}.jar`](https://mvnrepository.com/artifact/org.apache.gravitino/gravitino-tencent-bundle)
 file.
+2. Place the downloaded file into the Gravitino Fileset catalog classpath at 
`${GRAVITINO_HOME}/catalogs/fileset/libs/`.
+3. Start the Gravitino server by running the following command:
+
+```bash
+$ ${GRAVITINO_HOME}/bin/gravitino-server.sh start
+```
+
+Once the server is up and running, you can proceed to configure the Fileset 
catalog with COS. In the rest of this document we will use 
`http://localhost:8090` as the Gravitino server URL, replace with your actual 
server URL.
+
+## COS Catalog Configuration
+
+### COS Fileset Catalog Configuration
+
+In addition to the basic configurations mentioned in 
[Fileset-catalog-catalog-configuration](./fileset-catalog.md#catalog-properties),
 the following properties are required to configure a Fileset catalog with COS:
+
+| Configuration item            | Description                                  
                                                                                
                                                                                
                                                                                
                                                              | Default value | 
Required | Since version |
+|-------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------|----------|---------------|
+| `cos-region`                  | The region of the Tencent Cloud COS bucket, 
e.g. `ap-guangzhou`, `ap-shanghai`.                                             
                                                                                
                                                                                
                                                               | (none)        
| Yes      | 1.4.0         |
+| `cos-endpoint`                | The endpoint *suffix* of the Tencent Cloud 
COS service (mapped to `fs.cosn.bucket.endpoint_suffix`). It is a host suffix, 
not a full URL — e.g. `cos.ap-guangzhou.myqcloud.com`, **not** 
`https://cos.ap-guangzhou.myqcloud.com`. Optional; when not set, hadoop-cos 
derives it from `cos-region` (`cos.${region}.myqcloud.com`). Set this only if 
you need to point to a non-public endpoint (e.g. an internal/VPC endpoint).     
                                                                                
                           | (none)        | No       | 1.4.0         |
+| `cos-access-key-id`           | The static access key ID (Tencent Cloud 
`SecretId`) used to access COS data.                                            
                                                                                
                                                                                
                                                                   | (none)     
   | Yes      | 1.4.0         |
+| `cos-secret-access-key`       | The static secret access key (Tencent Cloud 
`SecretKey`) used to access COS data.                                           
                                                                                
                                                                                
                                                               | (none)        
| Yes      | 1.4.0         |
+| `credential-providers`        | The credential provider types, separated by 
comma. The currently supported value is `cos-secret-key`. Setting this enables 
credential vending provided by the Gravitino server, so the GVFS client no 
longer needs `cos-access-key-id` / `cos-secret-access-key` locally. See 
[cos-credential-vending](#fileset-with-credential-vending) below for details. | 
(none)        | No       | 1.4.0         |
+
+:::note
+The fileset catalog automatically loads filesystem providers on the classpath. 
The COS provider is registered when the `gravitino-tencent-bundle` jar is 
present, so `default-filesystem-provider` and `filesystem-providers` do not 
need to be set.
+:::
+
+:::note
+`cos-region` is mandatory for hadoop-cos: signing requests, building the 
default endpoint and selecting the right CAM scope all require the region. Even 
if you also set `cos-endpoint`, please keep `cos-region` set.
+:::
+
+### Schema Configuration
+
+To create a schema, refer to [Schema 
configurations](./fileset-catalog.md#schema-properties).
+
+### Fileset Configuration
+
+For instructions on how to create a fileset, refer to [Fileset 
configurations](./fileset-catalog.md#fileset-properties) for more details.
+
+## Create the Catalog, Schema, and Fileset
+
+This section will show you how to use the Fileset catalog with COS in 
Gravitino, including detailed examples.
+
+### Step 1: Create a Fileset Catalog with COS
+
+First, you need to create a Fileset catalog for COS. The following examples 
demonstrate how to create a Fileset catalog with COS:
+
+<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": "test_catalog",
+  "type": "FILESET",
+  "comment": "This is a COS fileset catalog",
+  "properties": {
+    "location": "cosn://my-bucket-1250000000/root",
+    "cos-region": "ap-guangzhou",
+    "cos-access-key-id": "access_key",
+    "cos-secret-access-key": "secret_key"
+  }
+}' http://localhost:8090/api/metalakes/metalake/catalogs
+```
+
+</TabItem>
+<TabItem value="java" label="Java">
+
+```java
+GravitinoClient gravitinoClient = GravitinoClient
+    .builder("http://localhost:8090";)
+    .withMetalake("metalake")
+    .build();
+
+Map<String, String> cosProperties = ImmutableMap.<String, String>builder()
+    .put("location", "cosn://my-bucket-1250000000/root")
+    .put("cos-region", "ap-guangzhou")
+    .put("cos-access-key-id", "access_key")
+    .put("cos-secret-access-key", "secret_key")
+    .build();
+
+Catalog cosCatalog = gravitinoClient.createCatalog("test_catalog",
+    Type.FILESET,
+    "This is a COS fileset catalog",
+    cosProperties);
+// ...
+
+```
+
+</TabItem>
+<TabItem value="python" label="Python">
+
+```python
+gravitino_client: GravitinoClient = 
GravitinoClient(uri="http://localhost:8090";, metalake_name="metalake")
+cos_properties = {
+    "location": "cosn://my-bucket-1250000000/root",
+    "cos-region": "ap-guangzhou",
+    "cos-access-key-id": "access_key",
+    "cos-secret-access-key": "secret_key"
+}
+
+cos_catalog = gravitino_client.create_catalog(name="test_catalog",
+                                              
catalog_type=Catalog.Type.FILESET,
+                                              provider=None,
+                                              comment="This is a COS fileset 
catalog",
+                                              properties=cos_properties)
+```
+
+</TabItem>
+</Tabs>
+
+:::note
+Tencent Cloud COS bucket names always end with the appid suffix, for example 
`my-bucket-1250000000`. Use that full bucket name in `location` and in any 
`cosn://` URI.
+:::
+
+### Step 2: Create a Schema
+
+Once the Fileset catalog with COS is created, you can create a schema inside 
that catalog. Below are examples of how to do this:
+
+<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": "test_schema",
+  "comment": "This is a COS schema",
+  "properties": {
+    "location": "cosn://my-bucket-1250000000/root/schema"
+  }
+}' http://localhost:8090/api/metalakes/metalake/catalogs/test_catalog/schemas
+```
+
+</TabItem>
+<TabItem value="java" label="Java">
+
+```java
+Catalog catalog = gravitinoClient.loadCatalog("test_catalog");
+
+SupportsSchemas supportsSchemas = catalog.asSchemas();
+
+Map<String, String> schemaProperties = ImmutableMap.<String, String>builder()
+    .put("location", "cosn://my-bucket-1250000000/root/schema")
+    .build();
+Schema schema = supportsSchemas.createSchema("test_schema",
+    "This is a COS schema",
+    schemaProperties
+);
+// ...
+```
+
+</TabItem>
+<TabItem value="python" label="Python">
+
+```python
+gravitino_client: GravitinoClient = 
GravitinoClient(uri="http://localhost:8090";, metalake_name="metalake")
+catalog: Catalog = gravitino_client.load_catalog(name="test_catalog")
+catalog.as_schemas().create_schema(name="test_schema",
+                                   comment="This is a COS schema",
+                                   properties={"location": 
"cosn://my-bucket-1250000000/root/schema"})
+```
+
+</TabItem>
+</Tabs>
+
+
+### Step 3: Create a Fileset
+
+Now that the schema is created, you can create a fileset inside it. Here's how:
+
+<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": "example_fileset",
+  "comment": "This is an example fileset",
+  "type": "MANAGED",
+  "storageLocation": "cosn://my-bucket-1250000000/root/schema/example_fileset",
+  "properties": {
+    "k1": "v1"
+  }
+}' 
http://localhost:8090/api/metalakes/metalake/catalogs/test_catalog/schemas/test_schema/filesets
+```
+
+</TabItem>
+<TabItem value="java" label="Java">
+
+```java
+GravitinoClient gravitinoClient = GravitinoClient
+    .builder("http://localhost:8090";)
+    .withMetalake("metalake")
+    .build();
+
+Catalog catalog = gravitinoClient.loadCatalog("test_catalog");
+FilesetCatalog filesetCatalog = catalog.asFilesetCatalog();
+
+Map<String, String> propertiesMap = ImmutableMap.<String, String>builder()
+        .put("k1", "v1")
+        .build();
+
+filesetCatalog.createFileset(
+    NameIdentifier.of("test_schema", "example_fileset"),
+    "This is an example fileset",
+    Fileset.Type.MANAGED,
+    "cosn://my-bucket-1250000000/root/schema/example_fileset",
+    propertiesMap,
+);
+```
+
+</TabItem>
+<TabItem value="python" label="Python">
+
+```python
+gravitino_client: GravitinoClient = 
GravitinoClient(uri="http://localhost:8090";, metalake_name="metalake")
+
+catalog: Catalog = gravitino_client.load_catalog(name="test_catalog")
+catalog.as_fileset_catalog().create_fileset(ident=NameIdentifier.of("test_schema",
 "example_fileset"),
+                                            type=Fileset.Type.MANAGED,
+                                            comment="This is an example 
fileset",
+                                            
storage_location="cosn://my-bucket-1250000000/root/schema/example_fileset",
+                                            properties={"k1": "v1"})
+```
+
+</TabItem>
+</Tabs>
+
+## Access a Fileset with COS
+
+### Access the Fileset with the GVFS Java Client
+
+To access fileset with COS using the GVFS Java client, based on the [basic 
GVFS configurations](./how-to-use-gvfs.md#configuration-1), you need to add the 
following configurations:
+
+| Configuration item      | Description                                        
          | Default value | Required | Since version |
+|-------------------------|--------------------------------------------------------------|---------------|----------|---------------|
+| `cos-region`            | The region of the Tencent Cloud COS bucket.        
          | (none)        | Yes      | 1.4.0         |
+| `cos-endpoint`          | The endpoint *suffix* of the Tencent Cloud COS 
service (e.g. `cos.ap-guangzhou.myqcloud.com`, not a full URL). Optional. | 
(none)        | No       | 1.4.0         |
+| `cos-access-key-id`     | The access key ID (Tencent Cloud SecretId) for COS 
data.     | (none)        | Yes      | 1.4.0         |
+| `cos-secret-access-key` | The secret access key (Tencent Cloud SecretKey) 
for COS data.| (none)        | Yes      | 1.4.0         |
+
+:::note
+If the catalog has enabled [credential 
vending](security/credential-vending.md), the AK/SK properties above can be 
omitted. More details can be found in [Fileset with credential 
vending](#fileset-with-credential-vending).
+:::
+
+```java
+Configuration conf = new Configuration();
+conf.set("fs.AbstractFileSystem.gvfs.impl", 
"org.apache.gravitino.filesystem.hadoop.Gvfs");
+conf.set("fs.gvfs.impl", 
"org.apache.gravitino.filesystem.hadoop.GravitinoVirtualFileSystem");
+conf.set("fs.gravitino.server.uri", "http://localhost:8090";);
+conf.set("fs.gravitino.client.metalake", "test_metalake");
+conf.set("cos-region", "ap-guangzhou");
+conf.set("cos-access-key-id", "access_key");
+conf.set("cos-secret-access-key", "secret_key");
+Path filesetPath = new 
Path("gvfs://fileset/test_catalog/test_schema/test_fileset/new_dir");
+FileSystem fs = filesetPath.getFileSystem(conf);
+fs.mkdirs(filesetPath);
+...
+```
+
+Similar to Spark configurations, you need to add COS (bundle) jars to the 
classpath according to your environment.
+If you want to customise your hadoop version or there is already a hadoop 
version in your project, you can add the following dependencies to your 
`pom.xml`:
+
+```xml
+  <dependency>
+    <groupId>org.apache.hadoop</groupId>
+    <artifactId>hadoop-common</artifactId>
+    <version>${HADOOP_VERSION}</version>
+  </dependency>
+
+  <!-- hadoop-cos is published by Tencent Cloud, not by Apache Hadoop. -->
+  <dependency>
+    <groupId>com.qcloud.cos</groupId>
+    <artifactId>hadoop-cos</artifactId>
+    <version>3.3.0-8.3.23</version>
+  </dependency>
+
+  <dependency>
+    <groupId>org.apache.gravitino</groupId>
+    <artifactId>gravitino-filesystem-hadoop3-runtime</artifactId>
+    <version>${GRAVITINO_VERSION}</version>
+  </dependency>
+```
+
+:::note
+Unlike the S3, OSS, GCS and Azure connectors, COS does **not** ship with 
Apache Hadoop. The HCFS adapter for COS is published by Tencent Cloud as 
`com.qcloud.cos:hadoop-cos`. Make sure the version you pick is compatible with 
your Hadoop version (the `<hadoop>-<sdk>` form encodes both, e.g. 
`3.3.0-8.3.23` targets Hadoop 3.3.0).
+:::
+
+:::note
+Since version 1.4.0, the `gravitino-tencent` JAR is no longer required 
separately, as it is included in the `gravitino-filesystem-hadoop3-runtime` JAR.
+:::

Review Comment:
   You can remove this block.



##########
docs/fileset-catalog.md:
##########
@@ -12,9 +12,10 @@ Fileset catalog is a fileset catalog that using Hadoop 
Compatible File System (H
 the storage location of the fileset. It supports the local filesystem and 
HDFS. Since
 0.7.0-incubating, Gravitino supports [S3](fileset-catalog-with-s3.md), 
[GCS](fileset-catalog-with-gcs.md),
 [OSS](fileset-catalog-with-oss.md) and [Azure Blob 
Storage](fileset-catalog-with-adls.md) through Fileset catalog.
+Since 1.3.0, Gravitino also supports [Tencent Cloud 
COS](fileset-catalog-with-cos.md).

Review Comment:
   1.4.0?



##########
catalogs/catalog-fileset/src/test/java/org/apache/gravitino/catalog/fileset/integration/test/FilesetCOSCatalogIT.java:
##########
@@ -0,0 +1,219 @@
+/*
+ * 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 org.apache.gravitino.catalog.fileset.integration.test;
+
+import static 
org.apache.gravitino.catalog.fileset.FilesetCatalogPropertiesMetadata.FILESYSTEM_PROVIDERS;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Maps;
+import java.io.IOException;
+import java.net.URI;
+import java.util.Map;
+import org.apache.gravitino.Catalog;
+import org.apache.gravitino.NameIdentifier;
+import org.apache.gravitino.Schema;
+import org.apache.gravitino.file.Fileset;
+import org.apache.gravitino.integration.test.util.GravitinoITUtils;
+import org.apache.gravitino.storage.COSProperties;
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.fs.FileSystem;
+import org.apache.hadoop.fs.Path;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.condition.EnabledIf;
+import org.junit.platform.commons.util.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Integration test for the fileset catalog backed by Tencent Cloud COS. It is 
disabled unless the
+ * required environment variables (COS_*) are present, mirroring the OSS / AWS 
counterparts.
+ */
+@EnabledIf(value = "cosIsConfigured", disabledReason = "Tencent Cloud COS is 
not configured.")
+public class FilesetCOSCatalogIT extends FilesetCatalogIT {

Review Comment:
   Please also add GVFS-related ITs to cover the changes.



##########
docs/fileset-catalog-with-cos.md:
##########
@@ -0,0 +1,548 @@
+---
+title: "Fileset Catalog with COS"
+slug: "/fileset-catalog-with-cos"
+date: 2026-06-17
+keyword: "Fileset catalog COS Tencent"
+license: "This software is licensed under the Apache License version 2."
+---
+
+## Introduction
+
+This document explains how to configure a Fileset catalog with Tencent Cloud 
COS (Cloud Object Storage) in Gravitino.
+
+## Prerequisites

Review Comment:
   Have you tested manually based on the document?



##########
docs/fileset-catalog-with-cos.md:
##########
@@ -0,0 +1,548 @@
+---
+title: "Fileset Catalog with COS"
+slug: "/fileset-catalog-with-cos"
+date: 2026-06-17
+keyword: "Fileset catalog COS Tencent"
+license: "This software is licensed under the Apache License version 2."
+---
+
+## Introduction
+
+This document explains how to configure a Fileset catalog with Tencent Cloud 
COS (Cloud Object Storage) in Gravitino.
+
+## Prerequisites
+
+To set up a Fileset catalog with COS, follow these steps:
+
+1. Download the 
[`gravitino-tencent-bundle-${gravitino-version}.jar`](https://mvnrepository.com/artifact/org.apache.gravitino/gravitino-tencent-bundle)
 file.
+2. Place the downloaded file into the Gravitino Fileset catalog classpath at 
`${GRAVITINO_HOME}/catalogs/fileset/libs/`.
+3. Start the Gravitino server by running the following command:
+
+```bash
+$ ${GRAVITINO_HOME}/bin/gravitino-server.sh start
+```
+
+Once the server is up and running, you can proceed to configure the Fileset 
catalog with COS. In the rest of this document we will use 
`http://localhost:8090` as the Gravitino server URL, replace with your actual 
server URL.
+
+## COS Catalog Configuration
+
+### COS Fileset Catalog Configuration
+
+In addition to the basic configurations mentioned in 
[Fileset-catalog-catalog-configuration](./fileset-catalog.md#catalog-properties),
 the following properties are required to configure a Fileset catalog with COS:
+
+| Configuration item            | Description                                  
                                                                                
                                                                                
                                                                                
                                                              | Default value | 
Required | Since version |
+|-------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------|----------|---------------|
+| `cos-region`                  | The region of the Tencent Cloud COS bucket, 
e.g. `ap-guangzhou`, `ap-shanghai`.                                             
                                                                                
                                                                                
                                                               | (none)        
| Yes      | 1.4.0         |
+| `cos-endpoint`                | The endpoint *suffix* of the Tencent Cloud 
COS service (mapped to `fs.cosn.bucket.endpoint_suffix`). It is a host suffix, 
not a full URL — e.g. `cos.ap-guangzhou.myqcloud.com`, **not** 
`https://cos.ap-guangzhou.myqcloud.com`. Optional; when not set, hadoop-cos 
derives it from `cos-region` (`cos.${region}.myqcloud.com`). Set this only if 
you need to point to a non-public endpoint (e.g. an internal/VPC endpoint).     
                                                                                
                           | (none)        | No       | 1.4.0         |
+| `cos-access-key-id`           | The static access key ID (Tencent Cloud 
`SecretId`) used to access COS data.                                            
                                                                                
                                                                                
                                                                   | (none)     
   | Yes      | 1.4.0         |
+| `cos-secret-access-key`       | The static secret access key (Tencent Cloud 
`SecretKey`) used to access COS data.                                           
                                                                                
                                                                                
                                                               | (none)        
| Yes      | 1.4.0         |
+| `credential-providers`        | The credential provider types, separated by 
comma. The currently supported value is `cos-secret-key`. Setting this enables 
credential vending provided by the Gravitino server, so the GVFS client no 
longer needs `cos-access-key-id` / `cos-secret-access-key` locally. See 
[cos-credential-vending](#fileset-with-credential-vending) below for details. | 
(none)        | No       | 1.4.0         |
+
+:::note
+The fileset catalog automatically loads filesystem providers on the classpath. 
The COS provider is registered when the `gravitino-tencent-bundle` jar is 
present, so `default-filesystem-provider` and `filesystem-providers` do not 
need to be set.
+:::
+
+:::note
+`cos-region` is mandatory for hadoop-cos: signing requests, building the 
default endpoint and selecting the right CAM scope all require the region. Even 
if you also set `cos-endpoint`, please keep `cos-region` set.
+:::
+
+### Schema Configuration
+
+To create a schema, refer to [Schema 
configurations](./fileset-catalog.md#schema-properties).
+
+### Fileset Configuration
+
+For instructions on how to create a fileset, refer to [Fileset 
configurations](./fileset-catalog.md#fileset-properties) for more details.
+
+## Create the Catalog, Schema, and Fileset
+
+This section will show you how to use the Fileset catalog with COS in 
Gravitino, including detailed examples.
+
+### Step 1: Create a Fileset Catalog with COS
+
+First, you need to create a Fileset catalog for COS. The following examples 
demonstrate how to create a Fileset catalog with COS:
+
+<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": "test_catalog",
+  "type": "FILESET",
+  "comment": "This is a COS fileset catalog",
+  "properties": {
+    "location": "cosn://my-bucket-1250000000/root",
+    "cos-region": "ap-guangzhou",
+    "cos-access-key-id": "access_key",
+    "cos-secret-access-key": "secret_key"
+  }
+}' http://localhost:8090/api/metalakes/metalake/catalogs
+```
+
+</TabItem>
+<TabItem value="java" label="Java">
+
+```java
+GravitinoClient gravitinoClient = GravitinoClient
+    .builder("http://localhost:8090";)
+    .withMetalake("metalake")
+    .build();
+
+Map<String, String> cosProperties = ImmutableMap.<String, String>builder()
+    .put("location", "cosn://my-bucket-1250000000/root")
+    .put("cos-region", "ap-guangzhou")
+    .put("cos-access-key-id", "access_key")
+    .put("cos-secret-access-key", "secret_key")
+    .build();
+
+Catalog cosCatalog = gravitinoClient.createCatalog("test_catalog",
+    Type.FILESET,
+    "This is a COS fileset catalog",
+    cosProperties);
+// ...
+
+```
+
+</TabItem>
+<TabItem value="python" label="Python">
+
+```python
+gravitino_client: GravitinoClient = 
GravitinoClient(uri="http://localhost:8090";, metalake_name="metalake")
+cos_properties = {
+    "location": "cosn://my-bucket-1250000000/root",
+    "cos-region": "ap-guangzhou",
+    "cos-access-key-id": "access_key",
+    "cos-secret-access-key": "secret_key"
+}
+
+cos_catalog = gravitino_client.create_catalog(name="test_catalog",
+                                              
catalog_type=Catalog.Type.FILESET,
+                                              provider=None,
+                                              comment="This is a COS fileset 
catalog",
+                                              properties=cos_properties)
+```
+
+</TabItem>
+</Tabs>
+
+:::note
+Tencent Cloud COS bucket names always end with the appid suffix, for example 
`my-bucket-1250000000`. Use that full bucket name in `location` and in any 
`cosn://` URI.
+:::
+
+### Step 2: Create a Schema
+
+Once the Fileset catalog with COS is created, you can create a schema inside 
that catalog. Below are examples of how to do this:
+
+<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": "test_schema",
+  "comment": "This is a COS schema",
+  "properties": {
+    "location": "cosn://my-bucket-1250000000/root/schema"
+  }
+}' http://localhost:8090/api/metalakes/metalake/catalogs/test_catalog/schemas
+```
+
+</TabItem>
+<TabItem value="java" label="Java">
+
+```java
+Catalog catalog = gravitinoClient.loadCatalog("test_catalog");
+
+SupportsSchemas supportsSchemas = catalog.asSchemas();
+
+Map<String, String> schemaProperties = ImmutableMap.<String, String>builder()
+    .put("location", "cosn://my-bucket-1250000000/root/schema")
+    .build();
+Schema schema = supportsSchemas.createSchema("test_schema",
+    "This is a COS schema",
+    schemaProperties
+);
+// ...
+```
+
+</TabItem>
+<TabItem value="python" label="Python">
+
+```python
+gravitino_client: GravitinoClient = 
GravitinoClient(uri="http://localhost:8090";, metalake_name="metalake")
+catalog: Catalog = gravitino_client.load_catalog(name="test_catalog")
+catalog.as_schemas().create_schema(name="test_schema",
+                                   comment="This is a COS schema",
+                                   properties={"location": 
"cosn://my-bucket-1250000000/root/schema"})
+```
+
+</TabItem>
+</Tabs>
+
+
+### Step 3: Create a Fileset
+
+Now that the schema is created, you can create a fileset inside it. Here's how:
+
+<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": "example_fileset",
+  "comment": "This is an example fileset",
+  "type": "MANAGED",
+  "storageLocation": "cosn://my-bucket-1250000000/root/schema/example_fileset",
+  "properties": {
+    "k1": "v1"
+  }
+}' 
http://localhost:8090/api/metalakes/metalake/catalogs/test_catalog/schemas/test_schema/filesets
+```
+
+</TabItem>
+<TabItem value="java" label="Java">
+
+```java
+GravitinoClient gravitinoClient = GravitinoClient
+    .builder("http://localhost:8090";)
+    .withMetalake("metalake")
+    .build();
+
+Catalog catalog = gravitinoClient.loadCatalog("test_catalog");
+FilesetCatalog filesetCatalog = catalog.asFilesetCatalog();
+
+Map<String, String> propertiesMap = ImmutableMap.<String, String>builder()
+        .put("k1", "v1")
+        .build();
+
+filesetCatalog.createFileset(
+    NameIdentifier.of("test_schema", "example_fileset"),
+    "This is an example fileset",
+    Fileset.Type.MANAGED,
+    "cosn://my-bucket-1250000000/root/schema/example_fileset",
+    propertiesMap,
+);
+```
+
+</TabItem>
+<TabItem value="python" label="Python">
+
+```python
+gravitino_client: GravitinoClient = 
GravitinoClient(uri="http://localhost:8090";, metalake_name="metalake")
+
+catalog: Catalog = gravitino_client.load_catalog(name="test_catalog")
+catalog.as_fileset_catalog().create_fileset(ident=NameIdentifier.of("test_schema",
 "example_fileset"),
+                                            type=Fileset.Type.MANAGED,
+                                            comment="This is an example 
fileset",
+                                            
storage_location="cosn://my-bucket-1250000000/root/schema/example_fileset",
+                                            properties={"k1": "v1"})
+```
+
+</TabItem>
+</Tabs>
+
+## Access a Fileset with COS
+
+### Access the Fileset with the GVFS Java Client
+
+To access fileset with COS using the GVFS Java client, based on the [basic 
GVFS configurations](./how-to-use-gvfs.md#configuration-1), you need to add the 
following configurations:
+
+| Configuration item      | Description                                        
          | Default value | Required | Since version |
+|-------------------------|--------------------------------------------------------------|---------------|----------|---------------|
+| `cos-region`            | The region of the Tencent Cloud COS bucket.        
          | (none)        | Yes      | 1.4.0         |
+| `cos-endpoint`          | The endpoint *suffix* of the Tencent Cloud COS 
service (e.g. `cos.ap-guangzhou.myqcloud.com`, not a full URL). Optional. | 
(none)        | No       | 1.4.0         |
+| `cos-access-key-id`     | The access key ID (Tencent Cloud SecretId) for COS 
data.     | (none)        | Yes      | 1.4.0         |
+| `cos-secret-access-key` | The secret access key (Tencent Cloud SecretKey) 
for COS data.| (none)        | Yes      | 1.4.0         |
+
+:::note
+If the catalog has enabled [credential 
vending](security/credential-vending.md), the AK/SK properties above can be 
omitted. More details can be found in [Fileset with credential 
vending](#fileset-with-credential-vending).
+:::
+
+```java
+Configuration conf = new Configuration();
+conf.set("fs.AbstractFileSystem.gvfs.impl", 
"org.apache.gravitino.filesystem.hadoop.Gvfs");
+conf.set("fs.gvfs.impl", 
"org.apache.gravitino.filesystem.hadoop.GravitinoVirtualFileSystem");
+conf.set("fs.gravitino.server.uri", "http://localhost:8090";);
+conf.set("fs.gravitino.client.metalake", "test_metalake");
+conf.set("cos-region", "ap-guangzhou");
+conf.set("cos-access-key-id", "access_key");
+conf.set("cos-secret-access-key", "secret_key");
+Path filesetPath = new 
Path("gvfs://fileset/test_catalog/test_schema/test_fileset/new_dir");
+FileSystem fs = filesetPath.getFileSystem(conf);
+fs.mkdirs(filesetPath);
+...
+```
+
+Similar to Spark configurations, you need to add COS (bundle) jars to the 
classpath according to your environment.
+If you want to customise your hadoop version or there is already a hadoop 
version in your project, you can add the following dependencies to your 
`pom.xml`:
+
+```xml
+  <dependency>
+    <groupId>org.apache.hadoop</groupId>
+    <artifactId>hadoop-common</artifactId>
+    <version>${HADOOP_VERSION}</version>
+  </dependency>
+
+  <!-- hadoop-cos is published by Tencent Cloud, not by Apache Hadoop. -->
+  <dependency>
+    <groupId>com.qcloud.cos</groupId>
+    <artifactId>hadoop-cos</artifactId>
+    <version>3.3.0-8.3.23</version>
+  </dependency>
+
+  <dependency>
+    <groupId>org.apache.gravitino</groupId>
+    <artifactId>gravitino-filesystem-hadoop3-runtime</artifactId>
+    <version>${GRAVITINO_VERSION}</version>
+  </dependency>
+```
+
+:::note
+Unlike the S3, OSS, GCS and Azure connectors, COS does **not** ship with 
Apache Hadoop. The HCFS adapter for COS is published by Tencent Cloud as 
`com.qcloud.cos:hadoop-cos`. Make sure the version you pick is compatible with 
your Hadoop version (the `<hadoop>-<sdk>` form encodes both, e.g. 
`3.3.0-8.3.23` targets Hadoop 3.3.0).
+:::
+
+:::note
+Since version 1.4.0, the `gravitino-tencent` JAR is no longer required 
separately, as it is included in the `gravitino-filesystem-hadoop3-runtime` JAR.
+:::
+
+Or use the bundle jar with Hadoop environment if there is no Hadoop 
environment:
+
+```xml
+  <dependency>
+    <groupId>org.apache.gravitino</groupId>
+    <artifactId>gravitino-tencent-bundle</artifactId>
+    <version>${GRAVITINO_VERSION}</version>
+  </dependency>
+
+  <dependency>
+    <groupId>org.apache.gravitino</groupId>
+    <artifactId>gravitino-filesystem-hadoop3-runtime</artifactId>
+    <version>${GRAVITINO_VERSION}</version>
+  </dependency>
+```
+
+### Access the Fileset with Spark
+
+The following code snippet shows how to use **PySpark 3.5.0 with Hadoop 
environment(Hadoop 3.3.4)** to access the fileset:
+
+Before running the following code, you need to install required packages:
+
+```bash
+pip install pyspark==3.5.0
+pip install apache-gravitino==${GRAVITINO_VERSION}
+```
+Then you can run the following code:
+
+```python
+from pyspark.sql import SparkSession
+import os
+
+gravitino_url = "http://localhost:8090";
+metalake_name = "test"
+
+catalog_name = "your_cos_catalog"
+schema_name = "your_cos_schema"
+fileset_name = "your_cos_fileset"
+
+# JDK8 as follows. JDK17 will be slightly different, you need to add
+# '--conf 
"spark.driver.extraJavaOptions=--add-opens=java.base/sun.nio.ch=ALL-UNNAMED"
+#  --conf 
"spark.executor.extraJavaOptions=--add-opens=java.base/sun.nio.ch=ALL-UNNAMED"'
+# to the submit args.
+os.environ["PYSPARK_SUBMIT_ARGS"] = (
+    "--jars "
+    "/path/to/gravitino-filesystem-hadoop3-runtime-{gravitino-version}.jar,"
+    "/path/to/hadoop-cos-3.3.0-8.3.23.jar,"
+    "/path/to/cos_api-bundle-5.6.227.jar "
+    "--master local[1] pyspark-shell"
+)
+spark = SparkSession.builder \
+    .appName("cos_fileset_test") \
+    .config("spark.hadoop.fs.AbstractFileSystem.gvfs.impl", 
"org.apache.gravitino.filesystem.hadoop.Gvfs") \
+    .config("spark.hadoop.fs.gvfs.impl", 
"org.apache.gravitino.filesystem.hadoop.GravitinoVirtualFileSystem") \
+    .config("spark.hadoop.fs.gravitino.server.uri", gravitino_url) \
+    .config("spark.hadoop.fs.gravitino.client.metalake", "test") \
+    .config("spark.hadoop.cos-region", "ap-guangzhou") \
+    .config("spark.hadoop.cos-access-key-id", os.environ["COS_ACCESS_KEY_ID"]) 
\
+    .config("spark.hadoop.cos-secret-access-key", 
os.environ["COS_SECRET_ACCESS_KEY"]) \
+    .config("spark.driver.memory", "2g") \
+    .config("spark.driver.port", "2048") \
+    .getOrCreate()
+
+data = [("Alice", 25), ("Bob", 30), ("Cathy", 45)]
+columns = ["Name", "Age"]
+spark_df = spark.createDataFrame(data, schema=columns)
+gvfs_path = 
f"gvfs://fileset/{catalog_name}/{schema_name}/{fileset_name}/people"
+
+spark_df.coalesce(1).write \
+    .mode("overwrite") \
+    .option("header", "true") \
+    .csv(gvfs_path)
+```
+
+If your Spark is **without Hadoop environment**, you can use the following 
code snippet to access the fileset:
+
+```python
+## Replace the following code snippet with the above code snippet with the 
same environment variables
+
+os.environ["PYSPARK_SUBMIT_ARGS"] = "--jars 
/path/to/gravitino-tencent-bundle-{gravitino-version}.jar,/path/to/gravitino-filesystem-hadoop3-runtime-{gravitino-version}.jar
 --master local[1] pyspark-shell"
+```
+
+- 
[`gravitino-tencent-bundle-${gravitino-version}.jar`](https://mvnrepository.com/artifact/org.apache.gravitino/gravitino-tencent-bundle):
 A "fat" JAR that includes `gravitino-tencent` functionality and all necessary 
dependencies like `hadoop-cos` and the Tencent Cloud COS Java SDK. Use this if 
your Spark environment doesn't have a pre-existing Hadoop setup.
+- 
[`gravitino-filesystem-hadoop3-runtime-${gravitino-version}.jar`](https://mvnrepository.com/artifact/org.apache.gravitino/gravitino-filesystem-hadoop3-runtime):
 A "fat" JAR that bundles Gravitino's virtual filesystem client and includes 
the functionality of `gravitino-tencent`. It is required for accessing 
Gravitino filesets.
+- `hadoop-cos-3.3.0-8.3.23.jar` and `cos_api-bundle-5.6.227.jar`: The 
Tencent-Cloud-published HCFS adapter and Java SDK for COS. If you are running 
in an existing Hadoop environment, you need to provide these JARs yourself; 
they are not part of the standard Apache Hadoop distribution and must be 
downloaded from Maven Central or Tencent's release page.
+- 
[`gravitino-tencent-${gravitino-version}.jar`](https://mvnrepository.com/artifact/org.apache.gravitino/gravitino-tencent):
 A "thin" JAR that only provides the COS integration code. Its functionality is 
already included in the `gravitino-tencent-bundle` and 
`gravitino-filesystem-hadoop3-runtime` JARs, so you do not need to add it as a 
direct dependency unless you want to manage all Hadoop and COS dependencies 
manually.

Review Comment:
   Why do we need `hadoop-cos-3.3.0-8.3.23.jar`, 
`gravitino-tencent-${gravitino-version}.jar` here again?
   
   `gravitino-tencent-bundle-${gravitino-version}.jar` and 
`gravitino-filesystem-hadoop3-runtime-${gravitino-version}.jar` should be 
enough.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


Reply via email to