support_kit/service/
service_config.rs

1use serde::{Deserialize, Serialize};
2use service_manager::ServiceManagerKind;
3
4use super::ServiceName;
5
6#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, bon::Builder)]
7#[serde(rename_all = "kebab-case")]
8pub struct ServiceConfig {
9    #[serde(default)]
10    #[builder(default, into)]
11    pub name: ServiceName,
12
13    #[serde(default)]
14    #[builder(default)]
15    pub system: bool,
16
17    /// The kind of service manager to use. Defaults to system native.
18    #[serde(default)]
19    #[builder(into)]
20    pub service_manager: Option<ServiceManagerKind>,
21}
22
23impl ServiceConfig {
24    pub fn name(&self) -> ServiceName {
25        self.name.clone()
26    }
27}
28
29impl From<&str> for ServiceConfig {
30    fn from(name: &str) -> Self {
31        Self::builder().name(name).build()
32    }
33}
34
35#[test]
36fn default_name() -> Result<(), Box<dyn std::error::Error>> {
37    use figment::Jail;
38
39    let config: ServiceConfig = serde_json::from_str(r#"{}"#)?;
40
41    assert_eq!(config, ServiceConfig::default());
42
43    let config: ServiceConfig = serde_json::from_str(
44        r#"
45        {
46            "name": "support-kit"
47        }
48        "#,
49    )?;
50
51    assert_eq!(config, ServiceConfig::default());
52
53    let config: ServiceConfig = serde_json::from_str(
54        r#"
55        {
56            "name": "support-kit"
57        }
58        "#,
59    )?;
60
61    assert_eq!(config, ServiceConfig::builder().build());
62
63    Jail::expect_with(|jail| {
64        jail.set_env("CARGO_PKG_NAME", "consumer-package");
65
66        let config: ServiceConfig = serde_json::from_str(
67            r#"
68            {
69                "name": "consumer-package"
70            }
71            "#,
72        )
73        .expect("failed to parse");
74
75        assert_eq!(config, ServiceConfig::default());
76
77        Ok(())
78    });
79
80    Ok(())
81}
82
83#[test]
84fn custom_service_label() -> Result<(), Box<dyn std::error::Error>> {
85    let config: ServiceConfig = serde_json::from_str(
86        r#"
87        {
88            "name": "custom-name"
89        }
90        "#,
91    )?;
92
93    assert_eq!(config, ServiceConfig::builder().name("custom-name").build());
94
95    Ok(())
96}
97
98#[test]
99fn default_system_service() -> Result<(), Box<dyn std::error::Error>> {
100    assert_eq!(
101        ServiceConfig::default(),
102        ServiceConfig::builder().system(false).build()
103    );
104
105    Ok(())
106}
107
108#[test]
109fn system_service() -> Result<(), Box<dyn std::error::Error>> {
110    let config: ServiceConfig = serde_json::from_str(
111        r#"
112        {
113            "system": true
114        }
115        "#,
116    )?;
117
118    assert_eq!(config, ServiceConfig::builder().system(true).build());
119
120    Ok(())
121}
122
123#[test]
124fn custom_service_manager() -> Result<(), Box<dyn std::error::Error>> {
125    use service_manager::ServiceManagerKind::*;
126
127    let expectations = [
128        ("systemd", Systemd),
129        ("winsw", WinSw),
130        ("launchd", Launchd),
131        ("openrc", OpenRc),
132        ("rcd", Rcd),
133        ("sc", Sc),
134    ];
135
136    for (input, expected) in expectations {
137        let config: ServiceConfig = serde_json::from_str(&format!(
138            r#"
139            {{
140                "service-manager": "{input}"
141            }}
142            "#
143        ))?;
144
145        assert_eq!(
146            config,
147            ServiceConfig::builder().service_manager(expected).build()
148        );
149    }
150
151    Ok(())
152}