• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

yaleman / maremma / #261

02 Mar 2025 09:32AM UTC coverage: 74.826% (-0.2%) from 75.046%
#261

push

web-flow
fixes (#143)

* fix: match instead of let some
* fix: clippyism
* fix: explicitly set the number of threads tokio uses

1 of 1 new or added line in 1 file covered. (100.0%)

80 existing lines in 10 files now uncovered.

2042 of 2729 relevant lines covered (74.83%)

2.52 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

53.57
/src/cli.rs
1
//! Main app CLI-related things
2

3
use std::path::PathBuf;
4

5
use clap::*;
6

7
use crate::prelude::ServiceType;
8
use crate::DEFAULT_CONFIG_FILE;
9

10
#[derive(Parser, Clone, Default, Debug)]
11
/// Shared configuration options
12
pub struct SharedOpts {
13
    #[clap(short, long,action = clap::ArgAction::SetTrue)]
14
    /// Enable debug logging
15
    pub debug: Option<bool>,
16
    #[clap(long,action = clap::ArgAction::SetTrue)]
17
    /// Enable database debug logging because it's SUPER noisy
18
    pub db_debug: Option<bool>,
19

20
    #[clap(short, long, help=format!("Path to the configuration file. Defaults to {}", crate::DEFAULT_CONFIG_FILE), default_value=crate::DEFAULT_CONFIG_FILE)]
21
    /// Defaults to [crate::DEFAULT_CONFIG_FILE]
22
    pub config: PathBuf,
23

24
    #[cfg(debug_assertions)]
25
    #[clap(long, help = "Enable tokio console integration for testing",action = clap::ArgAction::SetTrue)]
26
    tokio_console: Option<bool>,
27
}
28

29
#[derive(Parser, Clone, Default)]
30
/// Run the platform
31
pub struct Run {
32
    #[clap(flatten)]
33
    sharedopts: SharedOpts,
34
}
35
#[derive(Parser, Clone)]
36
/// Show the parsed configuration
37
pub struct ShowConfig {
38
    #[clap(flatten)]
39
    /// Shared options
40
    pub sharedopts: SharedOpts,
41
}
42

43
#[derive(Parser, Clone, Debug)]
44
/// Run a single check manually and exit
45
pub struct OneShotCmd {
46
    #[clap(flatten)]
47
    /// Shared options
48
    pub sharedopts: SharedOpts,
49
    /// The check to run
50
    pub check: ServiceType,
51
    /// Hostname to target
52
    pub hostname: String,
53
    /// Extra configuration, parsed as JSON
54
    pub service_config: String,
55

56
    /// Show the config options for the service
57
    #[clap(long)]
58
    pub show_config: bool,
59
}
60

61
/// Sub commands
62
#[derive(Subcommand, Clone)]
63
pub enum Actions {
64
    #[clap(name = "run")]
65
    /// Run the server
66
    Run(Run),
67
    #[clap(name = "check-config")]
68
    /// Checks the system configuration is valid
69
    CheckConfig(ShowConfig),
70
    #[clap(name = "show-config")]
71
    /// Show the system configuration
72
    ShowConfig(ShowConfig),
73
    #[clap(name = "export-config-schema")]
74
    /// Export a JSON schema for the config file
75
    ExportConfigSchema,
76
    #[clap(name = "oneshot")]
77
    /// Run a single check manually and exit
78
    OneShot(OneShotCmd),
79
}
80

81
#[derive(Parser, Clone)]
82
/// Maremma, protecting the herd.
83
pub struct CliOpts {
84
    /// Subcommands
85
    #[command(subcommand)]
86
    pub action: Actions,
87
}
88

89
impl CliOpts {
90
    /// Gets the config path
91
    pub fn config(&self) -> PathBuf {
1✔
92
        match &self.action {
1✔
93
            Actions::Run(run) => run.sharedopts.config.clone(),
1✔
UNCOV
94
            Actions::CheckConfig(run) => run.sharedopts.config.clone(),
×
95
            Actions::ShowConfig(run) => run.sharedopts.config.clone(),
1✔
UNCOV
96
            Actions::OneShot(run) => run.sharedopts.config.clone(),
×
97
            Actions::ExportConfigSchema => PathBuf::from(DEFAULT_CONFIG_FILE),
1✔
98
        }
99
    }
100

101
    /// Gets the debug field
102
    pub fn debug(&self) -> bool {
1✔
103
        match &self.action {
1✔
104
            Actions::Run(run) => run.sharedopts.debug.unwrap_or(false),
1✔
UNCOV
105
            Actions::CheckConfig(run) => run.sharedopts.debug.unwrap_or(false),
×
106
            Actions::ShowConfig(run) => run.sharedopts.debug.unwrap_or(false),
1✔
UNCOV
107
            Actions::OneShot(run) => run.sharedopts.debug.unwrap_or(false),
×
108
            Actions::ExportConfigSchema => false,
1✔
109
        }
110
    }
111
    /// Gets the db_debug field
112
    pub fn db_debug(&self) -> bool {
1✔
113
        match &self.action {
1✔
114
            Actions::Run(run) => run.sharedopts.db_debug.unwrap_or(false),
1✔
UNCOV
115
            Actions::CheckConfig(run) => run.sharedopts.db_debug.unwrap_or(false),
×
116
            Actions::ShowConfig(run) => run.sharedopts.db_debug.unwrap_or(false),
1✔
UNCOV
117
            Actions::OneShot(run) => run.sharedopts.db_debug.unwrap_or(false),
×
118
            Actions::ExportConfigSchema => false,
1✔
119
        }
120
    }
121
    /// Gets the tokio_console field
UNCOV
122
    pub fn tokio_console(&self) -> bool {
×
123
        {
124
            #[cfg(not(debug_assertions))]
125
            false
126
        }
127

128
        #[cfg(debug_assertions)]
UNCOV
129
        match &self.action {
×
UNCOV
130
            Actions::Run(run) => run.sharedopts.tokio_console.unwrap_or(false),
×
UNCOV
131
            Actions::CheckConfig(run) => run.sharedopts.tokio_console.unwrap_or(false),
×
UNCOV
132
            Actions::ShowConfig(run) => run.sharedopts.tokio_console.unwrap_or(false),
×
UNCOV
133
            Actions::OneShot(run) => run.sharedopts.tokio_console.unwrap_or(false),
×
UNCOV
134
            Actions::ExportConfigSchema => false,
×
135
        }
136
    }
137
}
138

139
#[cfg(test)]
140
mod tests {
141
    use super::*;
142
    #[test]
143
    fn test_cliopts() {
144
        let test_list = vec![
145
            ("maremma run --debug", true),
146
            ("maremma run", false),
147
            ("maremma show-config --debug", true),
148
            ("maremma show-config", false),
149
            ("maremma export-config-schema", false),
150
        ];
151

152
        for (args, debug) in test_list {
153
            let args = args.split_whitespace().collect::<Vec<&str>>();
154
            let opts = CliOpts::parse_from(args);
155

156
            assert_eq!(opts.debug(), debug);
157
        }
158

159
        let test_list = vec![
160
            (
161
                "maremma run --config /tmp/config.toml",
162
                PathBuf::from("/tmp/config.toml"),
163
            ),
164
            (
165
                "maremma show-config --config /tmp/config.toml",
166
                PathBuf::from("/tmp/config.toml"),
167
            ),
168
            ("maremma run", PathBuf::from(crate::DEFAULT_CONFIG_FILE)),
169
            (
170
                "maremma show-config",
171
                PathBuf::from(crate::DEFAULT_CONFIG_FILE),
172
            ),
173
            (
174
                "maremma export-config-schema",
175
                PathBuf::from(crate::DEFAULT_CONFIG_FILE),
176
            ),
177
        ];
178

179
        for (args, expected_config) in test_list {
180
            let args = args.split_whitespace().collect::<Vec<&str>>();
181
            let opts = CliOpts::parse_from(args);
182

183
            assert_eq!(opts.config(), expected_config);
184
        }
185
    }
186

187
    // TODO: work out how to run the export subcommand, capture the result and confirm it's doing what it says
188

189
    #[test]
190
    fn test_db_debug() {
191
        let test_list = vec![
192
            ("maremma run --db-debug", true),
193
            ("maremma run", false),
194
            ("maremma show-config --db-debug", true),
195
            ("maremma show-config", false),
196
            ("maremma export-config-schema", false),
197
        ];
198

199
        for (args, db_debug) in test_list {
200
            let args = args.split_whitespace().collect::<Vec<&str>>();
201
            let opts = CliOpts::parse_from(args);
202

203
            assert_eq!(opts.db_debug(), db_debug);
204
        }
205
    }
206
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc