1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
|
use std::error::Error;
use std::net::IpAddr;
use console::Style;
use dialoguer::{theme::ColorfulTheme, Confirm, Input, Select};
#[derive(Debug)]
#[allow(dead_code)]
struct Config {
interface: IpAddr,
hostname: String,
use_acme: bool,
private_key: Option<String>,
cert: Option<String>,
}
fn init_config() -> Result<Option<Config>, Box<dyn Error>> {
let theme = ColorfulTheme {
values_style: Style::new().yellow().dim(),
..ColorfulTheme::default()
};
println!("Welcome to the setup wizard");
if !Confirm::with_theme(&theme)
.with_prompt("Do you want to continue?")
.interact()?
{
return Ok(None);
}
let interface = Input::with_theme(&theme)
.with_prompt("Interface")
.default("127.0.0.1".parse().unwrap())
.interact()?;
let hostname = Input::with_theme(&theme)
.with_prompt("Hostname")
.interact()?;
let tls = Select::with_theme(&theme)
.with_prompt("Configure TLS")
.default(0)
.item("automatic with ACME")
.item("manual")
.item("no")
.interact()?;
let (private_key, cert, use_acme) = match tls {
0 => (Some("acme.pkey".into()), Some("acme.cert".into()), true),
1 => (
Some(
Input::with_theme(&theme)
.with_prompt(" Path to private key")
.interact()?,
),
Some(
Input::with_theme(&theme)
.with_prompt(" Path to certificate")
.interact()?,
),
false,
),
_ => (None, None, false),
};
Ok(Some(Config {
hostname,
interface,
private_key,
cert,
use_acme,
}))
}
fn main() {
match init_config() {
Ok(None) => println!("Aborted."),
Ok(Some(config)) => println!("{:#?}", config),
Err(err) => println!("error: {}", err),
}
}
|