Skip to main content

risedev/
service_config.rs

1// Copyright 2022 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
15use serde::{Deserialize, Serialize};
16
17#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
18#[serde(rename_all = "kebab-case")]
19#[serde(deny_unknown_fields)]
20pub struct ComputeNodeConfig {
21    #[serde(rename = "use")]
22    phantom_use: Option<String>,
23    pub id: String,
24
25    pub address: String,
26    #[serde(with = "string")]
27    pub port: u16,
28    pub listen_address: String,
29    pub exporter_port: u16,
30    pub async_stack_trace: String,
31    pub enable_tiered_cache: bool,
32
33    pub provide_minio: Option<Vec<MinioConfig>>,
34    pub provide_meta_node: Option<Vec<MetaNodeConfig>>,
35    pub provide_compute_node: Option<Vec<ComputeNodeConfig>>,
36    pub provide_opendal: Option<Vec<OpendalConfig>>,
37    pub provide_aws_s3: Option<Vec<AwsS3Config>>,
38    pub provide_moat: Option<Vec<MoatConfig>>,
39    pub provide_tempo: Option<Vec<TempoConfig>>,
40    pub user_managed: bool,
41    pub resource_group: String,
42
43    pub total_memory_bytes: usize,
44    pub parallelism: usize,
45    pub role: String,
46}
47
48#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
49#[serde(rename_all = "kebab-case")]
50#[serde(deny_unknown_fields)]
51pub enum MetaBackend {
52    Memory,
53    Sqlite,
54    Postgres,
55    Mysql,
56    Env,
57}
58
59#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
60#[serde(rename_all = "kebab-case")]
61#[serde(deny_unknown_fields)]
62pub struct MetaNodeConfig {
63    #[serde(rename = "use")]
64    phantom_use: Option<String>,
65    pub id: String,
66
67    pub address: String,
68    #[serde(with = "string")]
69    pub port: u16,
70    pub listen_address: String,
71    pub dashboard_port: u16,
72    pub exporter_port: u16,
73
74    pub user_managed: bool,
75
76    pub meta_backend: MetaBackend,
77    pub provide_sqlite_backend: Option<Vec<SqliteConfig>>,
78    pub provide_postgres_backend: Option<Vec<PostgresConfig>>,
79    pub provide_mysql_backend: Option<Vec<MySqlConfig>>,
80    pub provide_prometheus: Option<Vec<PrometheusConfig>>,
81
82    pub provide_compute_node: Option<Vec<ComputeNodeConfig>>,
83    pub provide_compactor: Option<Vec<CompactorConfig>>,
84
85    pub provide_tempo: Option<Vec<TempoConfig>>,
86
87    pub provide_aws_s3: Option<Vec<AwsS3Config>>,
88    pub provide_minio: Option<Vec<MinioConfig>>,
89    pub provide_opendal: Option<Vec<OpendalConfig>>,
90    pub provide_moat: Option<Vec<MoatConfig>>,
91}
92
93#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
94#[serde(rename_all = "kebab-case")]
95#[serde(deny_unknown_fields)]
96pub struct FrontendConfig {
97    #[serde(rename = "use")]
98    phantom_use: Option<String>,
99    pub id: String,
100
101    pub address: String,
102    #[serde(with = "string")]
103    pub port: u16,
104    pub listen_address: String,
105    pub exporter_port: u16,
106    pub health_check_port: u16,
107
108    pub provide_meta_node: Option<Vec<MetaNodeConfig>>,
109    pub provide_tempo: Option<Vec<TempoConfig>>,
110    pub provide_prometheus: Option<Vec<PrometheusConfig>>,
111
112    pub user_managed: bool,
113}
114
115#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
116#[serde(rename_all = "kebab-case")]
117#[serde(deny_unknown_fields)]
118pub struct CompactorConfig {
119    #[serde(rename = "use")]
120    phantom_use: Option<String>,
121    pub id: String,
122
123    pub address: String,
124    #[serde(with = "string")]
125    pub port: u16,
126    pub listen_address: String,
127    pub exporter_port: u16,
128
129    pub provide_minio: Option<Vec<MinioConfig>>,
130
131    pub provide_meta_node: Option<Vec<MetaNodeConfig>>,
132    pub provide_tempo: Option<Vec<TempoConfig>>,
133
134    pub user_managed: bool,
135    pub compaction_worker_threads_number: Option<usize>,
136
137    pub compactor_mode: String,
138}
139
140#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
141#[serde(rename_all = "kebab-case")]
142#[serde(deny_unknown_fields)]
143pub struct MinioConfig {
144    #[serde(rename = "use")]
145    phantom_use: Option<String>,
146    pub id: String,
147
148    pub address: String,
149    #[serde(with = "string")]
150    pub port: u16,
151    pub listen_address: String,
152
153    pub console_address: String,
154    #[serde(with = "string")]
155    pub console_port: u16,
156
157    pub root_user: String,
158    pub root_password: String,
159    pub hummock_bucket: String,
160
161    pub provide_prometheus: Option<Vec<PrometheusConfig>>,
162
163    // For rate limiting minio in a test environment.
164    pub api_requests_max: usize,
165    pub api_requests_deadline: String,
166}
167
168#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
169#[serde(rename_all = "kebab-case")]
170#[serde(deny_unknown_fields)]
171pub struct SqliteConfig {
172    #[serde(rename = "use")]
173    phantom_use: Option<String>,
174    pub id: String,
175
176    pub file: String,
177}
178
179#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
180#[serde(rename_all = "kebab-case")]
181#[serde(deny_unknown_fields)]
182pub struct PrometheusConfig {
183    #[serde(rename = "use")]
184    phantom_use: Option<String>,
185    pub id: String,
186
187    pub address: String,
188    #[serde(with = "string")]
189    pub port: u16,
190    pub listen_address: String,
191
192    pub remote_write: bool,
193    pub remote_write_region: String,
194    pub remote_write_url: String,
195
196    pub scrape_interval: String,
197
198    pub provide_compute_node: Option<Vec<ComputeNodeConfig>>,
199    pub provide_meta_node: Option<Vec<MetaNodeConfig>>,
200    pub provide_minio: Option<Vec<MinioConfig>>,
201    pub provide_compactor: Option<Vec<CompactorConfig>>,
202    pub provide_frontend: Option<Vec<FrontendConfig>>,
203}
204
205#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
206#[serde(rename_all = "kebab-case")]
207#[serde(deny_unknown_fields)]
208pub struct GrafanaConfig {
209    #[serde(rename = "use")]
210    phantom_use: Option<String>,
211    pub id: String,
212    pub address: String,
213    pub listen_address: String,
214    pub port: u16,
215
216    pub provide_prometheus: Option<Vec<PrometheusConfig>>,
217    pub provide_tempo: Option<Vec<TempoConfig>>,
218}
219
220#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
221#[serde(rename_all = "kebab-case")]
222#[serde(deny_unknown_fields)]
223pub struct TempoConfig {
224    #[serde(rename = "use")]
225    phantom_use: Option<String>,
226    pub id: String,
227
228    pub listen_address: String,
229    pub address: String,
230    pub port: u16,
231    pub otlp_port: u16,
232    pub max_bytes_per_trace: usize,
233}
234
235#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
236#[serde(rename_all = "kebab-case")]
237#[serde(deny_unknown_fields)]
238pub struct AwsS3Config {
239    #[serde(rename = "use")]
240    phantom_use: Option<String>,
241    pub id: String,
242    pub bucket: String,
243}
244
245#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
246#[serde(rename_all = "kebab-case")]
247#[serde(deny_unknown_fields)]
248pub struct MotoConfig {
249    #[serde(rename = "use")]
250    phantom_use: Option<String>,
251    pub id: String,
252
253    pub address: String,
254    #[serde(with = "string")]
255    pub port: u16,
256
257    pub image: String,
258    pub user_managed: bool,
259
260    pub provide_minio: Option<Vec<MinioConfig>>,
261}
262
263#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
264#[serde(rename_all = "kebab-case")]
265#[serde(deny_unknown_fields)]
266pub struct OpendalConfig {
267    #[serde(rename = "use")]
268    phantom_use: Option<String>,
269
270    pub id: String,
271    pub engine: String,
272    pub namenode: String,
273    pub bucket: String,
274}
275
276#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
277#[serde(rename_all = "kebab-case")]
278#[serde(deny_unknown_fields)]
279pub struct KafkaConfig {
280    #[serde(rename = "use")]
281    phantom_use: Option<String>,
282    pub id: String,
283
284    /// Advertise address
285    pub address: String,
286    #[serde(with = "string")]
287    pub port: u16,
288    /// Port for other services in docker. They need to connect to `host.docker.internal`, while the host
289    /// need to connect to `localhost`.
290    pub docker_port: u16,
291
292    #[serde(with = "string")]
293    pub controller_port: u16,
294
295    pub image: String,
296    pub persist_data: bool,
297    pub node_id: u32,
298
299    pub user_managed: bool,
300}
301
302#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
303#[serde(rename_all = "kebab-case")]
304#[serde(deny_unknown_fields)]
305pub struct SchemaRegistryConfig {
306    #[serde(rename = "use")]
307    phantom_use: Option<String>,
308
309    pub id: String,
310
311    pub address: String,
312    #[serde(with = "string")]
313    pub port: u16,
314
315    pub provide_kafka: Option<Vec<KafkaConfig>>,
316
317    pub image: String,
318    /// Redpanda supports schema registry natively. You can configure a `user_managed` schema registry
319    /// to use with redpanda.
320    pub user_managed: bool,
321}
322
323#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
324#[serde(rename_all = "kebab-case")]
325#[serde(deny_unknown_fields)]
326pub struct PubsubConfig {
327    #[serde(rename = "use")]
328    phantom_use: Option<String>,
329    pub id: String,
330    #[serde(default)]
331    pub user_managed: bool,
332    #[serde(with = "string")]
333    pub port: u16,
334    pub address: String,
335
336    pub persist_data: bool,
337}
338
339#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
340#[serde(rename_all = "kebab-case")]
341#[serde(deny_unknown_fields)]
342pub struct PulsarConfig {
343    #[serde(rename = "use")]
344    phantom_use: Option<String>,
345    pub id: String,
346
347    pub address: String,
348    pub broker_port: u16,
349    pub http_port: u16,
350
351    pub user_managed: bool,
352    pub image: String,
353    pub persist_data: bool,
354}
355
356#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
357#[serde(rename_all = "kebab-case")]
358#[serde(deny_unknown_fields)]
359pub struct RedisConfig {
360    #[serde(rename = "use")]
361    phantom_use: Option<String>,
362    pub id: String,
363
364    pub port: u16,
365    pub address: String,
366
367    pub image: String,
368    pub user_managed: bool,
369    pub persist_data: bool,
370}
371
372#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
373#[serde(rename_all = "kebab-case")]
374#[serde(deny_unknown_fields)]
375pub struct ClickHouseConfig {
376    #[serde(rename = "use")]
377    phantom_use: Option<String>,
378    pub id: String,
379
380    pub address: String,
381    pub http_port: u16,
382    pub native_port: u16,
383
384    pub user: String,
385    pub password: String,
386    pub database: String,
387
388    pub image: String,
389    pub user_managed: bool,
390    pub persist_data: bool,
391}
392
393#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
394#[serde(rename_all = "kebab-case")]
395#[serde(deny_unknown_fields)]
396pub enum Application {
397    Metastore,
398    Connector,
399}
400
401#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
402#[serde(rename_all = "kebab-case")]
403#[serde(deny_unknown_fields)]
404pub struct MySqlConfig {
405    #[serde(rename = "use")]
406    phantom_use: Option<String>,
407    pub id: String,
408
409    pub port: u16,
410    pub address: String,
411
412    pub user: String,
413    pub password: String,
414    pub database: String,
415
416    pub application: Application,
417    pub image: String,
418    pub user_managed: bool,
419    pub persist_data: bool,
420}
421
422#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
423#[serde(rename_all = "kebab-case")]
424#[serde(deny_unknown_fields)]
425pub struct PostgresConfig {
426    #[serde(rename = "use")]
427    phantom_use: Option<String>,
428    pub id: String,
429
430    pub port: u16,
431    pub address: String,
432
433    pub user: String,
434    pub password: String,
435    pub database: String,
436
437    pub application: Application,
438    pub image: String,
439    pub user_managed: bool,
440    pub persist_data: bool,
441
442    // Inject latency into any network calls to the postgres service.
443    pub latency_ms: u32,
444}
445
446#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
447#[serde(rename_all = "kebab-case")]
448#[serde(deny_unknown_fields)]
449pub struct SqlServerConfig {
450    #[serde(rename = "use")]
451    phantom_use: Option<String>,
452    pub id: String,
453
454    pub port: u16,
455    pub address: String,
456
457    pub user: String,
458    pub password: String,
459    pub database: String,
460
461    pub image: String,
462    pub user_managed: bool,
463    pub persist_data: bool,
464}
465
466#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
467#[serde(rename_all = "kebab-case")]
468#[serde(deny_unknown_fields)]
469pub struct MongoDbConfig {
470    #[serde(rename = "use")]
471    phantom_use: Option<String>,
472    pub id: String,
473
474    pub address: String,
475    pub port: u16,
476
477    pub image: String,
478    pub user_managed: bool,
479    pub persist_data: bool,
480}
481
482#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
483#[serde(rename_all = "kebab-case")]
484#[serde(deny_unknown_fields)]
485pub struct NatsConfig {
486    #[serde(rename = "use")]
487    phantom_use: Option<String>,
488    pub id: String,
489
490    pub address: String,
491    pub port: u16,
492    pub monitor_port: u16,
493
494    pub image: String,
495    pub user_managed: bool,
496    pub persist_data: bool,
497}
498
499#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
500#[serde(rename_all = "kebab-case")]
501#[serde(deny_unknown_fields)]
502pub struct MqttConfig {
503    #[serde(rename = "use")]
504    phantom_use: Option<String>,
505    pub id: String,
506
507    pub address: String,
508    pub port: u16,
509
510    pub image: String,
511    pub user_managed: bool,
512    pub persist_data: bool,
513}
514
515#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
516#[serde(rename_all = "kebab-case")]
517#[serde(deny_unknown_fields)]
518pub struct ElasticSearchConfig {
519    #[serde(rename = "use")]
520    phantom_use: Option<String>,
521    pub id: String,
522
523    pub address: String,
524    pub port: u16,
525
526    pub user: String,
527    pub password: String,
528
529    pub image: String,
530    pub user_managed: bool,
531    pub persist_data: bool,
532}
533
534#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
535#[serde(rename_all = "kebab-case")]
536#[serde(deny_unknown_fields)]
537pub struct OpenSearchConfig {
538    #[serde(rename = "use")]
539    phantom_use: Option<String>,
540    pub id: String,
541
542    pub address: String,
543    pub port: u16,
544
545    pub user: String,
546    pub password: String,
547
548    pub image: String,
549    pub user_managed: bool,
550    pub persist_data: bool,
551}
552
553#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
554#[serde(rename_all = "kebab-case")]
555#[serde(deny_unknown_fields)]
556pub struct LakekeeperConfig {
557    #[serde(rename = "use")]
558    phantom_use: Option<String>,
559    pub id: String,
560
561    pub port: u16,
562    pub address: String,
563
564    pub user_managed: bool,
565    pub persist_data: bool,
566
567    pub catalog_backend: String,
568    pub encryption_key: String,
569    pub provide_postgres_backend: Option<Vec<PostgresConfig>>,
570    pub provide_minio: Option<Vec<MinioConfig>>,
571}
572
573#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
574#[serde(rename_all = "kebab-case")]
575#[serde(deny_unknown_fields)]
576pub struct MoatConfig {
577    #[serde(rename = "use")]
578    phantom_use: Option<String>,
579    pub id: String,
580
581    pub address: String,
582    pub port: u16,
583
584    pub provide_minio: Option<Vec<MinioConfig>>,
585}
586
587/// All service configuration
588#[derive(Clone, Debug, PartialEq)]
589pub enum ServiceConfig {
590    ComputeNode(ComputeNodeConfig),
591    MetaNode(MetaNodeConfig),
592    Frontend(FrontendConfig),
593    Compactor(CompactorConfig),
594    Minio(MinioConfig),
595    Sqlite(SqliteConfig),
596    Prometheus(PrometheusConfig),
597    Grafana(GrafanaConfig),
598    Tempo(TempoConfig),
599    Opendal(OpendalConfig),
600    AwsS3(AwsS3Config),
601    Moto(MotoConfig),
602    Kafka(KafkaConfig),
603    SchemaRegistry(SchemaRegistryConfig),
604    Pubsub(PubsubConfig),
605    Pulsar(PulsarConfig),
606    Redis(RedisConfig),
607    ClickHouse(ClickHouseConfig),
608    MySql(MySqlConfig),
609    Postgres(PostgresConfig),
610    SqlServer(SqlServerConfig),
611    MongoDb(MongoDbConfig),
612    ElasticSearch(ElasticSearchConfig),
613    OpenSearch(OpenSearchConfig),
614    Nats(NatsConfig),
615    Mqtt(MqttConfig),
616    Lakekeeper(LakekeeperConfig),
617    Moat(MoatConfig),
618}
619
620#[derive(PartialEq, Eq, Hash, Debug)]
621pub enum TaskGroup {
622    RisingWave,
623    Observability,
624    Kafka,
625    Pubsub,
626    Pulsar,
627    MySql,
628    Postgres,
629    SqlServer,
630    MongoDb,
631    ElasticSearch,
632    OpenSearch,
633    Nats,
634    Mqtt,
635    Redis,
636    ClickHouse,
637    Lakekeeper,
638    Moat,
639}
640
641impl ServiceConfig {
642    pub fn id(&self) -> &str {
643        match self {
644            Self::ComputeNode(c) => &c.id,
645            Self::MetaNode(c) => &c.id,
646            Self::Frontend(c) => &c.id,
647            Self::Compactor(c) => &c.id,
648            Self::Minio(c) => &c.id,
649            Self::Sqlite(c) => &c.id,
650            Self::Prometheus(c) => &c.id,
651            Self::Grafana(c) => &c.id,
652            Self::Tempo(c) => &c.id,
653            Self::AwsS3(c) => &c.id,
654            Self::Moto(c) => &c.id,
655            Self::Kafka(c) => &c.id,
656            Self::Pubsub(c) => &c.id,
657            Self::Pulsar(c) => &c.id,
658            Self::Redis(c) => &c.id,
659            Self::ClickHouse(c) => &c.id,
660            Self::Opendal(c) => &c.id,
661            Self::MySql(c) => &c.id,
662            Self::Postgres(c) => &c.id,
663            Self::SqlServer(c) => &c.id,
664            Self::MongoDb(c) => &c.id,
665            Self::ElasticSearch(c) => &c.id,
666            Self::OpenSearch(c) => &c.id,
667            Self::Nats(c) => &c.id,
668            Self::Mqtt(c) => &c.id,
669            Self::SchemaRegistry(c) => &c.id,
670            Self::Lakekeeper(c) => &c.id,
671            Self::Moat(c) => &c.id,
672        }
673    }
674
675    /// Used to check whether the port is occupied before running the service.
676    pub fn port(&self) -> Option<u16> {
677        match self {
678            Self::ComputeNode(c) => Some(c.port),
679            Self::MetaNode(c) => Some(c.port),
680            Self::Frontend(c) => Some(c.port),
681            Self::Compactor(c) => Some(c.port),
682            Self::Minio(c) => Some(c.port),
683            Self::Sqlite(_) => None,
684            Self::Prometheus(c) => Some(c.port),
685            Self::Grafana(c) => Some(c.port),
686            Self::Tempo(c) => Some(c.port),
687            Self::AwsS3(_) => None,
688            Self::Moto(c) => Some(c.port),
689            Self::Kafka(c) => Some(c.port),
690            Self::Pubsub(c) => Some(c.port),
691            Self::Pulsar(c) => Some(c.http_port),
692            Self::Redis(c) => Some(c.port),
693            Self::ClickHouse(c) => Some(c.http_port),
694            Self::Opendal(_) => None,
695            Self::MySql(c) => Some(c.port),
696            Self::Postgres(c) => Some(c.port),
697            Self::SqlServer(c) => Some(c.port),
698            Self::MongoDb(c) => Some(c.port),
699            Self::ElasticSearch(c) => Some(c.port),
700            Self::OpenSearch(c) => Some(c.port),
701            Self::Nats(c) => Some(c.port),
702            Self::Mqtt(c) => Some(c.port),
703            Self::SchemaRegistry(c) => Some(c.port),
704            Self::Lakekeeper(c) => Some(c.port),
705            Self::Moat(c) => Some(c.port),
706        }
707    }
708
709    pub fn user_managed(&self) -> bool {
710        match self {
711            Self::ComputeNode(c) => c.user_managed,
712            Self::MetaNode(c) => c.user_managed,
713            Self::Frontend(c) => c.user_managed,
714            Self::Compactor(c) => c.user_managed,
715            Self::Minio(_c) => false,
716            Self::Sqlite(_c) => false,
717            Self::Prometheus(_c) => false,
718            Self::Grafana(_c) => false,
719            Self::Tempo(_c) => false,
720            Self::AwsS3(_c) => false,
721            Self::Moto(c) => c.user_managed,
722            Self::Kafka(c) => c.user_managed,
723            Self::Pubsub(c) => c.user_managed,
724            Self::Pulsar(c) => c.user_managed,
725            Self::Redis(c) => c.user_managed,
726            Self::ClickHouse(c) => c.user_managed,
727            Self::Opendal(_c) => false,
728            Self::MySql(c) => c.user_managed,
729            Self::Postgres(c) => c.user_managed,
730            Self::SqlServer(c) => c.user_managed,
731            Self::MongoDb(c) => c.user_managed,
732            Self::ElasticSearch(c) => c.user_managed,
733            Self::OpenSearch(c) => c.user_managed,
734            Self::Nats(c) => c.user_managed,
735            Self::Mqtt(c) => c.user_managed,
736            Self::SchemaRegistry(c) => c.user_managed,
737            Self::Lakekeeper(c) => c.user_managed,
738            Self::Moat(_c) => false,
739        }
740    }
741
742    pub fn task_group(&self) -> TaskGroup {
743        use TaskGroup::*;
744        match self {
745            ServiceConfig::ComputeNode(_)
746            | ServiceConfig::MetaNode(_)
747            | ServiceConfig::Frontend(_)
748            | ServiceConfig::Compactor(_)
749            | ServiceConfig::Minio(_)
750            | ServiceConfig::Sqlite(_) => RisingWave,
751            ServiceConfig::Prometheus(_) | ServiceConfig::Grafana(_) | ServiceConfig::Tempo(_) => {
752                Observability
753            }
754            ServiceConfig::Opendal(_) | ServiceConfig::AwsS3(_) => RisingWave,
755            ServiceConfig::Moto(_) => RisingWave,
756            ServiceConfig::Kafka(_) | ServiceConfig::SchemaRegistry(_) => Kafka,
757            ServiceConfig::Pubsub(_) => Pubsub,
758            ServiceConfig::Pulsar(_) => Pulsar,
759            ServiceConfig::Redis(_) => Redis,
760            ServiceConfig::ClickHouse(_) => ClickHouse,
761            ServiceConfig::MySql(my_sql_config) => {
762                if matches!(my_sql_config.application, Application::Metastore) {
763                    RisingWave
764                } else {
765                    MySql
766                }
767            }
768            ServiceConfig::Postgres(postgres_config) => {
769                if matches!(postgres_config.application, Application::Metastore) {
770                    RisingWave
771                } else {
772                    Postgres
773                }
774            }
775            ServiceConfig::SqlServer(_) => SqlServer,
776            ServiceConfig::MongoDb(_) => MongoDb,
777            ServiceConfig::ElasticSearch(_) => ElasticSearch,
778            ServiceConfig::OpenSearch(_) => OpenSearch,
779            ServiceConfig::Nats(_) => Nats,
780            ServiceConfig::Mqtt(_) => Mqtt,
781            ServiceConfig::Lakekeeper(_) => Lakekeeper,
782            ServiceConfig::Moat(_) => Moat,
783        }
784    }
785}
786
787mod string {
788    use std::fmt::Display;
789    use std::str::FromStr;
790
791    use serde::{Deserialize, Deserializer, Serializer, de};
792
793    pub fn serialize<T, S>(value: &T, serializer: S) -> Result<S::Ok, S::Error>
794    where
795        T: Display,
796        S: Serializer,
797    {
798        serializer.collect_str(value)
799    }
800
801    pub fn deserialize<'de, T, D>(deserializer: D) -> Result<T, D::Error>
802    where
803        T: FromStr,
804        T::Err: Display,
805        D: Deserializer<'de>,
806    {
807        String::deserialize(deserializer)?
808            .parse()
809            .map_err(de::Error::custom)
810    }
811}