risedev/
risedev_env.rs

1// Copyright 2025 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::{Application, HummockInMemoryStrategy, ServiceConfig, add_hummock_backend};
21
22/// Generate environment variables (put in file `.risingwave/config/risedev-env`)
23/// from the given service configurations to be used by future
24/// RiseDev commands, like `risedev ctl` or `risedev psql` ().
25pub fn generate_risedev_env(services: &Vec<ServiceConfig>) -> String {
26    let mut env = String::new();
27    for item in services {
28        match item {
29            ServiceConfig::ComputeNode(c) => {
30                // RW_HUMMOCK_URL
31                // If the cluster is launched without a shared storage, we will skip this.
32                {
33                    let mut cmd = Command::new("compute-node");
34                    if add_hummock_backend(
35                        "dummy",
36                        c.provide_opendal.as_ref().unwrap(),
37                        c.provide_minio.as_ref().unwrap(),
38                        c.provide_aws_s3.as_ref().unwrap(),
39                        c.provide_moat.as_ref().unwrap(),
40                        HummockInMemoryStrategy::Disallowed,
41                        &mut cmd,
42                    )
43                    .is_ok()
44                    {
45                        writeln!(
46                            env,
47                            "RW_HUMMOCK_URL=\"{}\"",
48                            cmd.get_args().nth(1).unwrap().to_str().unwrap()
49                        )
50                        .unwrap();
51                    }
52                }
53
54                // RW_META_ADDR
55                {
56                    let meta_node = &c.provide_meta_node.as_ref().unwrap()[0];
57                    writeln!(
58                        env,
59                        "RW_META_ADDR=\"http://{}:{}\"",
60                        meta_node.address, meta_node.port
61                    )
62                    .unwrap();
63                }
64            }
65            ServiceConfig::Frontend(c) => {
66                let listen_address = &c.listen_address;
67                writeln!(
68                    env,
69                    "RISEDEV_RW_FRONTEND_LISTEN_ADDRESS=\"{listen_address}\"",
70                )
71                .unwrap();
72                let port = &c.port;
73                writeln!(env, "RISEDEV_RW_FRONTEND_PORT=\"{port}\"",).unwrap();
74            }
75            ServiceConfig::Kafka(c) => {
76                let brokers = format!("{}:{}", c.address, c.port);
77                writeln!(env, r#"RISEDEV_KAFKA_BOOTSTRAP_SERVERS="{brokers}""#,).unwrap();
78                writeln!(env, r#"RISEDEV_KAFKA_WITH_OPTIONS_COMMON="connector='kafka',properties.bootstrap.server='{brokers}'""#).unwrap();
79                writeln!(env, r#"RPK_BROKERS="{brokers}""#).unwrap();
80            }
81            ServiceConfig::SchemaRegistry(c) => {
82                let url = format!("http://{}:{}", c.address, c.port);
83                writeln!(env, r#"RISEDEV_SCHEMA_REGISTRY_URL="{url}""#,).unwrap();
84                writeln!(env, r#"RPK_REGISTRY_HOSTS="{url}""#).unwrap();
85            }
86            ServiceConfig::Pulsar(c) => {
87                // These 2 names are NOT defined by Pulsar, but by us.
88                // The `pulsar-admin` CLI uses a `PULSAR_CLIENT_CONF` file with `brokerServiceUrl` and `webServiceUrl`
89                // It may be used by our upcoming `PulsarCat` #21401
90                writeln!(
91                    env,
92                    r#"PULSAR_BROKER_URL="pulsar://{}:{}""#,
93                    c.address, c.broker_port
94                )
95                .unwrap();
96                writeln!(
97                    env,
98                    r#"PULSAR_HTTP_URL="http://{}:{}""#,
99                    c.address, c.http_port
100                )
101                .unwrap();
102            }
103            ServiceConfig::MySql(c) if c.application != Application::Metastore => {
104                let host = &c.address;
105                let port = &c.port;
106                let user = &c.user;
107                let password = &c.password;
108                // These envs are used by `mysql` cli.
109                writeln!(env, r#"MYSQL_HOST="{host}""#,).unwrap();
110                writeln!(env, r#"MYSQL_TCP_PORT="{port}""#,).unwrap();
111                // Note: There's no env var for the username read by `mysql` cli. Here we set
112                // `RISEDEV_MYSQL_USER`, which will be read by `e2e_test/commands/mysql` when
113                // running `risedev slt`, as a wrapper of `mysql` cli.
114                writeln!(env, r#"RISEDEV_MYSQL_USER="{user}""#,).unwrap();
115                writeln!(env, r#"MYSQL_PWD="{password}""#,).unwrap();
116                // Note: user and password are not included in the common WITH options.
117                // It's expected to create another dedicated user for the source.
118                writeln!(env, r#"RISEDEV_MYSQL_WITH_OPTIONS_COMMON="connector='mysql-cdc',hostname='{host}',port='{port}'""#,).unwrap();
119            }
120            ServiceConfig::Pubsub(c) => {
121                let address = &c.address;
122                let port = &c.port;
123                writeln!(env, r#"PUBSUB_EMULATOR_HOST="{address}:{port}""#,).unwrap();
124                writeln!(env, r#"RISEDEV_PUBSUB_WITH_OPTIONS_COMMON="connector='google_pubsub',pubsub.emulator_host='{address}:{port}'""#,).unwrap();
125            }
126            ServiceConfig::Postgres(c) => {
127                let host = &c.address;
128                let port = &c.port;
129                let user = &c.user;
130                let password = &c.password;
131                let database = &c.database;
132                // These envs are used by `postgres` cli.
133                writeln!(env, r#"PGHOST="{host}""#,).unwrap();
134                writeln!(env, r#"PGPORT="{port}""#,).unwrap();
135                writeln!(env, r#"PGUSER="{user}""#,).unwrap();
136                writeln!(env, r#"PGPASSWORD="{password}""#,).unwrap();
137                writeln!(env, r#"PGDATABASE="{database}""#,).unwrap();
138                writeln!(
139                    env,
140                    r#"RISEDEV_POSTGRES_WITH_OPTIONS_COMMON="connector='postgres-cdc',hostname='{host}',port='{port}'""#,
141                )
142                .unwrap();
143            }
144            ServiceConfig::SqlServer(c) => {
145                let host = &c.address;
146                let port = &c.port;
147                let user = &c.user;
148                let password = &c.password;
149                let database = &c.database;
150                // These envs are used by `sqlcmd`.
151                writeln!(env, r#"SQLCMDSERVER="{host}""#,).unwrap();
152                writeln!(env, r#"SQLCMDPORT="{port}""#,).unwrap();
153                writeln!(env, r#"SQLCMDUSER="{user}""#,).unwrap();
154                writeln!(env, r#"SQLCMDPASSWORD="{password}""#,).unwrap();
155                writeln!(env, r#"SQLCMDDBNAME="{database}""#,).unwrap();
156                writeln!(
157                    env,
158                    r#"RISEDEV_SQLSERVER_WITH_OPTIONS_COMMON="connector='sqlserver-cdc',hostname='{host}',port='{port}',username='{user}',password='{password}',database.name='{database}'""#,
159                )
160                .unwrap();
161            }
162            ServiceConfig::MetaNode(meta_node_config) => {
163                writeln!(
164                    env,
165                    r#"RISEDEV_RW_META_DASHBOARD_ADDR="http://{}:{}""#,
166                    meta_node_config.address, meta_node_config.dashboard_port
167                )
168                .unwrap();
169            }
170            ServiceConfig::Lakekeeper(c) => {
171                let base_url = format!("http://{}:{}", c.address, c.port);
172                let catalog_url = format!("{}/catalog", base_url);
173                writeln!(env, r#"RISEDEV_LAKEKEEPER_URL="{base_url}""#,).unwrap();
174                writeln!(env, r#"LAKEKEEPER_CATALOG_URL="{catalog_url}""#,).unwrap();
175                writeln!(env, r#"RISEDEV_LAKEKEEPER_WITH_OPTIONS_COMMON="connector='iceberg',catalog.type='rest',catalog.uri='{catalog_url}'""#,).unwrap();
176            }
177            _ => {}
178        }
179    }
180    env
181}