Skip to main content

risedev/
risedev_env.rs

1// Copyright 2023 RisingWave Labs
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#![allow(clippy::doc_markdown)] // RiseDev
16
17use std::fmt::Write;
18use std::process::Command;
19
20use crate::{
21    Application, DORIS_CONTAINER_HOST, DORIS_CONTAINER_QUERY_PORT, HummockInMemoryStrategy,
22    STARROCKS_CONTAINER_HOST, STARROCKS_CONTAINER_QUERY_PORT, ServiceConfig, add_hummock_backend,
23};
24
25/// Generate environment variables (put in file `.risingwave/config/risedev-env`)
26/// from the given service configurations to be used by future
27/// RiseDev commands, like `risedev ctl` or `risedev psql` ().
28pub fn generate_risedev_env(services: &Vec<ServiceConfig>) -> String {
29    let mut env = String::new();
30    for item in services {
31        match item {
32            ServiceConfig::ComputeNode(c) => {
33                // RW_HUMMOCK_URL
34                // If the cluster is launched without a shared storage, we will skip this.
35                {
36                    let mut cmd = Command::new("compute-node");
37                    if add_hummock_backend(
38                        "dummy",
39                        c.provide_opendal.as_ref().unwrap(),
40                        c.provide_minio.as_ref().unwrap(),
41                        c.provide_aws_s3.as_ref().unwrap(),
42                        c.provide_moat.as_ref().unwrap(),
43                        HummockInMemoryStrategy::Disallowed,
44                        &mut cmd,
45                    )
46                    .is_ok()
47                    {
48                        writeln!(
49                            env,
50                            "RW_HUMMOCK_URL=\"{}\"",
51                            cmd.get_args().nth(1).unwrap().to_str().unwrap()
52                        )
53                        .unwrap();
54                    }
55                }
56
57                // RW_META_ADDR
58                {
59                    let meta_node = &c.provide_meta_node.as_ref().unwrap()[0];
60                    writeln!(
61                        env,
62                        "RW_META_ADDR=\"http://{}:{}\"",
63                        meta_node.address, meta_node.port
64                    )
65                    .unwrap();
66                }
67            }
68            ServiceConfig::Frontend(c) => {
69                let listen_address = &c.listen_address;
70                writeln!(
71                    env,
72                    "RISEDEV_RW_FRONTEND_LISTEN_ADDRESS=\"{listen_address}\"",
73                )
74                .unwrap();
75                let port = &c.port;
76                writeln!(env, "RISEDEV_RW_FRONTEND_PORT=\"{port}\"",).unwrap();
77            }
78            ServiceConfig::Kafka(c) => {
79                let brokers = format!("{}:{}", c.address, c.port);
80                writeln!(env, r#"RISEDEV_KAFKA_BOOTSTRAP_SERVERS="{brokers}""#,).unwrap();
81                writeln!(env, r#"RISEDEV_KAFKA_WITH_OPTIONS_COMMON="connector='kafka',properties.bootstrap.server='{brokers}'""#).unwrap();
82                writeln!(env, r#"RPK_BROKERS="{brokers}""#).unwrap();
83            }
84            ServiceConfig::SchemaRegistry(c) => {
85                let url = format!("http://{}:{}", c.address, c.port);
86                writeln!(env, r#"RISEDEV_SCHEMA_REGISTRY_URL="{url}""#,).unwrap();
87                writeln!(env, r#"RPK_REGISTRY_HOSTS="{url}""#).unwrap();
88            }
89            ServiceConfig::Pulsar(c) => {
90                // These 2 names are NOT defined by Pulsar, but by us.
91                // The `pulsar-admin` CLI uses a `PULSAR_CLIENT_CONF` file with `brokerServiceUrl` and `webServiceUrl`
92                // It may be used by our upcoming `PulsarCat` #21401
93                writeln!(
94                    env,
95                    r#"PULSAR_BROKER_URL="pulsar://{}:{}""#,
96                    c.address, c.broker_port
97                )
98                .unwrap();
99                writeln!(
100                    env,
101                    r#"PULSAR_HTTP_URL="http://{}:{}""#,
102                    c.address, c.http_port
103                )
104                .unwrap();
105            }
106            ServiceConfig::Redis(c) => {
107                let host = &c.address;
108                let port = &c.port;
109                let url = format!("redis://{host}:{port}/");
110                writeln!(env, r#"REDIS_HOST="{host}""#).unwrap();
111                writeln!(env, r#"REDIS_PORT="{port}""#).unwrap();
112                writeln!(env, r#"RISEDEV_REDIS_URL="{url}""#).unwrap();
113                if !c.user_managed {
114                    writeln!(env, r#"REDIS_CONTAINER="risedev-{}""#, c.id).unwrap();
115                }
116                writeln!(
117                    env,
118                    r#"RISEDEV_REDIS_WITH_OPTIONS_COMMON="connector='redis',redis.url='{url}'""#,
119                )
120                .unwrap();
121            }
122            ServiceConfig::ClickHouse(c) => {
123                let host = &c.address;
124                let http_port = &c.http_port;
125                let native_port = &c.native_port;
126                let user = &c.user;
127                let password = &c.password;
128                let database = &c.database;
129                let url = format!("http://{host}:{http_port}");
130                writeln!(env, r#"CLICKHOUSE_HOST="{host}""#).unwrap();
131                writeln!(env, r#"CLICKHOUSE_HTTP_PORT="{http_port}""#).unwrap();
132                writeln!(env, r#"CLICKHOUSE_NATIVE_PORT="{native_port}""#).unwrap();
133                writeln!(env, r#"CLICKHOUSE_USER="{user}""#).unwrap();
134                writeln!(env, r#"CLICKHOUSE_PASSWORD="{password}""#).unwrap();
135                writeln!(env, r#"CLICKHOUSE_DATABASE="{database}""#).unwrap();
136                writeln!(env, r#"RISEDEV_CLICKHOUSE_URL="{url}""#).unwrap();
137                if !c.user_managed {
138                    writeln!(env, r#"CLICKHOUSE_CONTAINER="risedev-{}""#, c.id).unwrap();
139                }
140                writeln!(
141                    env,
142                    r#"RISEDEV_CLICKHOUSE_WITH_OPTIONS_COMMON="connector='clickhouse',clickhouse.url='{url}',clickhouse.user='{user}',clickhouse.password='{password}',clickhouse.database='{database}'""#,
143                )
144                .unwrap();
145            }
146            ServiceConfig::Doris(c) => {
147                let host = &c.address;
148                let http_port = &c.http_port;
149                let query_port = &c.query_port;
150                let user = &c.user;
151                let password = &c.password;
152                let database = &c.database;
153                let admin_user = &c.admin_user;
154                let admin_password = &c.admin_password;
155                let url = format!("http://{host}:{http_port}");
156                writeln!(env, r#"DORIS_HOST="{host}""#).unwrap();
157                writeln!(env, r#"DORIS_HTTP_PORT="{http_port}""#).unwrap();
158                writeln!(env, r#"DORIS_QUERY_PORT="{query_port}""#).unwrap();
159                writeln!(env, r#"DORIS_USER="{user}""#).unwrap();
160                writeln!(env, r#"DORIS_PASSWORD="{password}""#).unwrap();
161                writeln!(env, r#"DORIS_DATABASE="{database}""#).unwrap();
162                writeln!(env, r#"DORIS_ADMIN_USER="{admin_user}""#).unwrap();
163                writeln!(env, r#"DORIS_ADMIN_PASSWORD="{admin_password}""#).unwrap();
164                if !c.user_managed {
165                    writeln!(env, r#"DORIS_CONTAINER="risedev-{}""#, c.id).unwrap();
166                    writeln!(env, r#"DORIS_CONTAINER_HOST="{DORIS_CONTAINER_HOST}""#).unwrap();
167                    writeln!(
168                        env,
169                        r#"DORIS_CONTAINER_QUERY_PORT="{DORIS_CONTAINER_QUERY_PORT}""#
170                    )
171                    .unwrap();
172                }
173                writeln!(
174                    env,
175                    r#"RISEDEV_DORIS_WITH_OPTIONS_COMMON="connector='doris',doris.url='{url}',doris.user='{user}',doris.password='{password}',doris.database='{database}'""#,
176                )
177                .unwrap();
178            }
179            ServiceConfig::Starrocks(c) => {
180                let host = &c.address;
181                let http_port = &c.http_port;
182                let query_port = &c.query_port;
183                let user = &c.user;
184                let password = &c.password;
185                let database = &c.database;
186                let admin_user = &c.admin_user;
187                let admin_password = &c.admin_password;
188                let database_is_disposable = !c.user_managed || c.database_is_disposable;
189
190                writeln!(env, r#"STARROCKS_HOST="{host}""#).unwrap();
191                writeln!(env, r#"STARROCKS_HTTP_PORT="{http_port}""#).unwrap();
192                writeln!(env, r#"STARROCKS_QUERY_PORT="{query_port}""#).unwrap();
193                writeln!(env, r#"STARROCKS_USER="{user}""#).unwrap();
194                writeln!(env, r#"STARROCKS_PASSWORD="{password}""#).unwrap();
195                writeln!(env, r#"STARROCKS_DATABASE="{database}""#).unwrap();
196                writeln!(env, r#"STARROCKS_ADMIN_USER="{admin_user}""#).unwrap();
197                writeln!(env, r#"STARROCKS_ADMIN_PASSWORD="{admin_password}""#).unwrap();
198                writeln!(
199                    env,
200                    r#"STARROCKS_DATABASE_IS_DISPOSABLE="{database_is_disposable}""#
201                )
202                .unwrap();
203                if !c.user_managed {
204                    writeln!(env, r#"STARROCKS_CONTAINER="risedev-{}""#, c.id).unwrap();
205                    writeln!(
206                        env,
207                        r#"STARROCKS_CONTAINER_HOST="{STARROCKS_CONTAINER_HOST}""#
208                    )
209                    .unwrap();
210                    writeln!(
211                        env,
212                        r#"STARROCKS_CONTAINER_QUERY_PORT="{STARROCKS_CONTAINER_QUERY_PORT}""#
213                    )
214                    .unwrap();
215                }
216                writeln!(
217                    env,
218                    r#"RISEDEV_STARROCKS_WITH_OPTIONS_COMMON="connector='starrocks',starrocks.host='{host}',starrocks.mysqlport='{query_port}',starrocks.httpport='{http_port}',starrocks.user='{user}',starrocks.password='{password}',starrocks.database='{database}'""#,
219                )
220                .unwrap();
221            }
222            ServiceConfig::MySql(c) if c.application != Application::Metastore => {
223                let host = &c.address;
224                let port = &c.port;
225                let user = &c.user;
226                let password = &c.password;
227                // These envs are used by `mysql` cli.
228                writeln!(env, r#"MYSQL_HOST="{host}""#,).unwrap();
229                writeln!(env, r#"MYSQL_TCP_PORT="{port}""#,).unwrap();
230                // Note: There's no env var for the username read by `mysql` cli. Here we set
231                // `RISEDEV_MYSQL_USER`, which will be read by `e2e_test/commands/mysql` when
232                // running `risedev slt`, as a wrapper of `mysql` cli.
233                writeln!(env, r#"RISEDEV_MYSQL_USER="{user}""#,).unwrap();
234                writeln!(env, r#"MYSQL_PWD="{password}""#,).unwrap();
235                // Note: user and password are not included in the common WITH options.
236                // It's expected to create another dedicated user for the source.
237                writeln!(env, r#"RISEDEV_MYSQL_WITH_OPTIONS_COMMON="connector='mysql-cdc',hostname='{host}',port='{port}'""#,).unwrap();
238            }
239            ServiceConfig::Pubsub(c) => {
240                let address = &c.address;
241                let port = &c.port;
242                writeln!(env, r#"PUBSUB_EMULATOR_HOST="{address}:{port}""#,).unwrap();
243                writeln!(env, r#"RISEDEV_PUBSUB_WITH_OPTIONS_COMMON="connector='google_pubsub',pubsub.emulator_host='{address}:{port}'""#,).unwrap();
244            }
245            ServiceConfig::Postgres(c) => {
246                let host = &c.address;
247                let port = &c.port;
248                let user = &c.user;
249                let password = &c.password;
250                let database = &c.database;
251                // These envs are used by `postgres` cli.
252                writeln!(env, r#"PGHOST="{host}""#,).unwrap();
253                writeln!(env, r#"PGPORT="{port}""#,).unwrap();
254                writeln!(env, r#"PGUSER="{user}""#,).unwrap();
255                writeln!(env, r#"PGPASSWORD="{password}""#,).unwrap();
256                writeln!(env, r#"PGDATABASE="{database}""#,).unwrap();
257                writeln!(
258                    env,
259                    r#"RISEDEV_POSTGRES_WITH_OPTIONS_COMMON="connector='postgres-cdc',hostname='{host}',port='{port}'""#,
260                )
261                .unwrap();
262            }
263            ServiceConfig::Oracle(c) => {
264                let host = &c.address;
265                let port = &c.port;
266                let user = &c.user;
267                let password = &c.password;
268                let database = &c.database;
269                let pdb = &c.pdb;
270                writeln!(env, r#"ORACLE_HOST="{host}""#).unwrap();
271                writeln!(env, r#"ORACLE_PORT="{port}""#).unwrap();
272                writeln!(env, r#"ORACLE_USER="{user}""#).unwrap();
273                writeln!(env, r#"ORACLE_PASSWORD="{password}""#).unwrap();
274                writeln!(env, r#"ORACLE_DATABASE="{database}""#).unwrap();
275                writeln!(env, r#"ORACLE_PDB="{pdb}""#).unwrap();
276                if !c.user_managed {
277                    writeln!(env, r#"ORACLE_CONTAINER="risedev-{}""#, c.id).unwrap();
278                }
279                writeln!(
280                    env,
281                    r#"RISEDEV_ORACLE_WITH_OPTIONS_COMMON="connector='oracle-cdc',hostname='{host}',port='{port}',username='{user}',password='{password}',database.name='{database}',database.pdb.name='{pdb}'""#,
282                )
283                .unwrap();
284            }
285            ServiceConfig::SqlServer(c) => {
286                let host = &c.address;
287                let port = &c.port;
288                let user = &c.user;
289                let password = &c.password;
290                let database = &c.database;
291                // These envs are used by `sqlcmd`.
292                writeln!(env, r#"SQLCMDSERVER="{host}""#,).unwrap();
293                writeln!(env, r#"SQLCMDPORT="{port}""#,).unwrap();
294                writeln!(env, r#"SQLCMDUSER="{user}""#,).unwrap();
295                writeln!(env, r#"SQLCMDPASSWORD="{password}""#,).unwrap();
296                writeln!(env, r#"SQLCMDDBNAME="{database}""#,).unwrap();
297                writeln!(
298                    env,
299                    r#"RISEDEV_SQLSERVER_WITH_OPTIONS_COMMON="connector='sqlserver-cdc',hostname='{host}',port='{port}',username='{user}',password='{password}',database.name='{database}'""#,
300                )
301                .unwrap();
302            }
303            ServiceConfig::MongoDb(c) => {
304                let host = &c.address;
305                let port = &c.port;
306                let url = format!("mongodb://{host}:{port}/?replicaSet=rs0");
307                writeln!(env, r#"MONGODB_HOST="{host}""#).unwrap();
308                writeln!(env, r#"MONGODB_PORT="{port}""#).unwrap();
309                writeln!(env, r#"MONGODB_URL="{url}""#).unwrap();
310                if !c.user_managed {
311                    writeln!(env, r#"MONGODB_CONTAINER="risedev-{}""#, c.id).unwrap();
312                }
313                writeln!(
314                    env,
315                    r#"RISEDEV_MONGODB_WITH_OPTIONS_COMMON="connector='mongodb',mongodb.url='{url}'""#,
316                )
317                .unwrap();
318            }
319            ServiceConfig::ElasticSearch(c) => {
320                let host = &c.address;
321                let port = &c.port;
322                let user = &c.user;
323                let password = &c.password;
324                let url = format!("http://{host}:{port}");
325                writeln!(env, r#"ELASTICSEARCH_HOST="{host}""#).unwrap();
326                writeln!(env, r#"ELASTICSEARCH_PORT="{port}""#).unwrap();
327                writeln!(env, r#"ELASTICSEARCH_USER="{user}""#).unwrap();
328                writeln!(env, r#"ELASTICSEARCH_PASSWORD="{password}""#).unwrap();
329                writeln!(env, r#"RISEDEV_ELASTICSEARCH_URL="{url}""#).unwrap();
330                writeln!(
331                    env,
332                    r#"RISEDEV_ELASTICSEARCH_WITH_OPTIONS_COMMON="connector='elasticsearch',url='{url}',username='{user}',password='{password}'""#,
333                )
334                .unwrap();
335                writeln!(env, r#"SEARCH_SINK_CONNECTOR="elasticsearch""#).unwrap();
336                writeln!(env, r#"SEARCH_SINK_CONNECTION_TYPE="elasticsearch""#).unwrap();
337                writeln!(env, r#"SEARCH_SINK_URL="{url}""#).unwrap();
338                writeln!(env, r#"SEARCH_SINK_USER="{user}""#).unwrap();
339                writeln!(env, r#"SEARCH_SINK_PASSWORD="{password}""#).unwrap();
340                writeln!(
341                    env,
342                    r#"SEARCH_SINK_WITH_OPTIONS_COMMON="connector='elasticsearch',url='{url}',username='{user}',password='{password}'""#,
343                )
344                .unwrap();
345                writeln!(
346                    env,
347                    r#"SEARCH_SINK_ROUTE_WITH_OPTIONS="connector='elasticsearch',connection=es_conn""#,
348                )
349                .unwrap();
350            }
351            ServiceConfig::OpenSearch(c) => {
352                let host = &c.address;
353                let port = &c.port;
354                let user = &c.user;
355                let password = &c.password;
356                let url = format!("http://{host}:{port}");
357                writeln!(env, r#"OPENSEARCH_HOST="{host}""#).unwrap();
358                writeln!(env, r#"OPENSEARCH_PORT="{port}""#).unwrap();
359                writeln!(env, r#"OPENSEARCH_USER="{user}""#).unwrap();
360                writeln!(env, r#"OPENSEARCH_PASSWORD="{password}""#).unwrap();
361                writeln!(env, r#"RISEDEV_OPENSEARCH_URL="{url}""#).unwrap();
362                writeln!(
363                    env,
364                    r#"RISEDEV_OPENSEARCH_WITH_OPTIONS_COMMON="connector='opensearch',url='{url}',username='{user}',password='{password}'""#,
365                )
366                .unwrap();
367                writeln!(env, r#"SEARCH_SINK_CONNECTOR="opensearch""#).unwrap();
368                writeln!(env, r#"SEARCH_SINK_CONNECTION_TYPE="elasticsearch""#).unwrap();
369                writeln!(env, r#"SEARCH_SINK_URL="{url}""#).unwrap();
370                writeln!(env, r#"SEARCH_SINK_USER="{user}""#).unwrap();
371                writeln!(env, r#"SEARCH_SINK_PASSWORD="{password}""#).unwrap();
372                writeln!(
373                    env,
374                    r#"SEARCH_SINK_WITH_OPTIONS_COMMON="connector='opensearch',url='{url}',username='{user}',password='{password}'""#,
375                )
376                .unwrap();
377                writeln!(
378                    env,
379                    r#"SEARCH_SINK_ROUTE_WITH_OPTIONS="connector='opensearch',url='{url}',username='{user}',password='{password}'""#,
380                )
381                .unwrap();
382            }
383            ServiceConfig::Nats(c) => {
384                let server_url = format!("nats://{}:{}", c.address, c.port);
385                writeln!(env, r#"NATS_SERVER_URL="{server_url}""#).unwrap();
386                writeln!(env, r#"RISEDEV_NATS_SERVER_URL="{server_url}""#).unwrap();
387                writeln!(
388                    env,
389                    r#"RISEDEV_NATS_WITH_OPTIONS_COMMON="connector='nats',server_url='{server_url}'""#,
390                )
391                .unwrap();
392            }
393            ServiceConfig::Mqtt(c) => {
394                let url = format!("tcp://{}:{}", c.address, c.port);
395                writeln!(env, r#"MQTT_URL="{url}""#).unwrap();
396                writeln!(env, r#"RISEDEV_MQTT_URL="{url}""#).unwrap();
397                writeln!(
398                    env,
399                    r#"RISEDEV_MQTT_WITH_OPTIONS_COMMON="connector='mqtt',url='{url}'""#,
400                )
401                .unwrap();
402            }
403            ServiceConfig::Minio(c) => {
404                let endpoint = format!("http://{}:{}", c.address, c.port);
405                writeln!(env, r#"RISEDEV_MINIO_ENDPOINT="{endpoint}""#).unwrap();
406                writeln!(env, r#"RISEDEV_MINIO_ACCESS_KEY="{0}""#, c.root_user).unwrap();
407                writeln!(env, r#"RISEDEV_MINIO_SECRET_KEY="{0}""#, c.root_password).unwrap();
408
409                writeln!(
410                    env,
411                    r#"RISEDEV_DELTALAKE_LOCATION="s3a://deltalake/deltalake-test""#
412                )
413                .unwrap();
414                writeln!(env, r#"RISEDEV_DELTALAKE_S3_ENDPOINT="{endpoint}""#).unwrap();
415                writeln!(env, r#"RISEDEV_DELTALAKE_S3_REGION="us-east-1""#).unwrap();
416                writeln!(env, r#"RISEDEV_DELTALAKE_S3_ACCESS_KEY="{0}""#, c.root_user).unwrap();
417                writeln!(
418                    env,
419                    r#"RISEDEV_DELTALAKE_S3_SECRET_KEY="{0}""#,
420                    c.root_password
421                )
422                .unwrap();
423            }
424            ServiceConfig::MetaNode(meta_node_config) => {
425                writeln!(
426                    env,
427                    r#"RISEDEV_RW_META_DASHBOARD_ADDR="http://{}:{}""#,
428                    meta_node_config.address, meta_node_config.dashboard_port
429                )
430                .unwrap();
431            }
432            ServiceConfig::Lakekeeper(c) => {
433                let base_url = format!("http://{}:{}", c.address, c.port);
434                let catalog_url = format!("{}/catalog", base_url);
435                writeln!(env, r#"RISEDEV_LAKEKEEPER_URL="{base_url}""#,).unwrap();
436                writeln!(env, r#"LAKEKEEPER_CATALOG_URL="{catalog_url}""#,).unwrap();
437                writeln!(env, r#"RISEDEV_LAKEKEEPER_WITH_OPTIONS_COMMON="connector='iceberg',catalog.type='rest',catalog.uri='{catalog_url}'""#,).unwrap();
438            }
439            ServiceConfig::Moto(c) => {
440                let endpoint = format!("http://{}:{}", c.address, c.port);
441                let glue_access_key = "my_access_id";
442                let glue_secret_key = "my_secret_key";
443                writeln!(env, r#"RISEDEV_MOTO_ENDPOINT="{endpoint}""#).unwrap();
444                writeln!(env, r#"RISEDEV_GLUE_ENDPOINT="{endpoint}""#).unwrap();
445                writeln!(env, r#"RW_TEST_GLUE_ENDPOINT="{endpoint}""#).unwrap();
446                writeln!(env, r#"RW_TEST_GLUE_ACCESS_KEY="{glue_access_key}""#).unwrap();
447                writeln!(env, r#"RW_TEST_GLUE_SECRET_KEY="{glue_secret_key}""#).unwrap();
448
449                if let Some(minio_configs) = &c.provide_minio
450                    && let Some(minio) = minio_configs.first()
451                {
452                    let s3_endpoint = format!("http://{}:{}", minio.address, minio.port);
453                    let warehouse_path = format!("s3://{}/iceberg", minio.hummock_bucket);
454                    writeln!(env, r#"RW_TEST_GLUE_S3_ENDPOINT="{s3_endpoint}""#).unwrap();
455                    writeln!(env, r#"RW_TEST_GLUE_S3_ACCESS_KEY="{0}""#, minio.root_user).unwrap();
456                    writeln!(
457                        env,
458                        r#"RW_TEST_GLUE_S3_SECRET_KEY="{0}""#,
459                        minio.root_password
460                    )
461                    .unwrap();
462                    writeln!(env, r#"RW_TEST_GLUE_WAREHOUSE_PATH="{warehouse_path}""#).unwrap();
463                    writeln!(env, r#"RISEDEV_GLUE_RUST_WITH_OPTIONS_COMMON="connector='iceberg',catalog.type='glue_rust',catalog.uri='{endpoint}',glue.endpoint='{endpoint}',glue.region='us-east-1',glue.access.key='{glue_access_key}',glue.secret.key='{glue_secret_key}',warehouse.path='{warehouse_path}',s3.endpoint='{s3_endpoint}',s3.region='us-east-1',s3.access.key='{0}',s3.secret.key='{1}',s3.path.style.access='true'""#, minio.root_user, minio.root_password).unwrap();
464                    writeln!(env, r#"RISEDEV_GLUE_JNI_WITH_OPTIONS_COMMON="connector='iceberg',catalog.type='glue',catalog.uri='{endpoint}',glue.endpoint='{endpoint}',glue.region='us-east-1',glue.access.key='{glue_access_key}',glue.secret.key='{glue_secret_key}',warehouse.path='{warehouse_path}',s3.endpoint='{s3_endpoint}',s3.region='us-east-1',s3.access.key='{0}',s3.secret.key='{1}',s3.path.style.access='true'""#, minio.root_user, minio.root_password).unwrap();
465                }
466            }
467            _ => {}
468        }
469    }
470    env
471}