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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
use std::str::FromStr;
#[derive(Debug, Parser)]
struct CommonOpt {
#[clap(short, long)]
pub debug: bool,
}
#[derive(Debug, Parser)]
struct PreProcOpt {
#[clap(flatten)]
pub copt: CommonOpt,
#[clap(parse(from_os_str), short, long = "input")]
pub input_path: PathBuf,
#[clap(parse(from_os_str), short, long = "output")]
pub output_path: PathBuf,
}
#[derive(Debug, Parser)]
struct SetupOpt {
#[clap(flatten)]
pub copt: CommonOpt,
#[clap(name = "target")]
pub target: TargetOpt,
#[clap(parse(from_os_str), short, long = "profile")]
pub profile_path: PathBuf,
}
#[derive(Debug, Parser)]
struct RunOpt {
#[clap(flatten)]
pub copt: CommonOpt,
#[clap(name = "target")]
pub target: TargetOpt,
#[clap(name = "test_type")]
pub test_type: TestTypeOpt,
#[clap(parse(from_os_str), short, long = "profile")]
pub profile_path: PathBuf,
}
#[derive(Debug, Subcommand)]
pub(crate) enum TargetOpt {
#[clap(name = "ds")]
Ds,
#[clap(name = "kanidm")]
Kanidm,
#[clap(name = "kanidm_ldap")]
KanidmLdap,
}
impl FromStr for TargetOpt {
type Err = &'static str;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"ds" => Ok(TargetOpt::Ds),
"kanidm" => Ok(TargetOpt::Kanidm),
"kanidm_ldap" => Ok(TargetOpt::KanidmLdap),
_ => Err("Invalid target type. Must be ds, kanidm, or kanidm_ldap"),
}
}
}
#[derive(Debug, Subcommand)]
pub(crate) enum TestTypeOpt {
#[clap(name = "search-basic")]
SearchBasic,
}
impl FromStr for TestTypeOpt {
type Err = &'static str;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"search-basic" => Ok(TestTypeOpt::SearchBasic),
_ => Err("Invalid test type."),
}
}
}
impl std::fmt::Display for TestTypeOpt {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match &self {
TestTypeOpt::SearchBasic => write!(f, "search-basic"),
}
}
}
#[derive(Debug, Parser)]
#[clap(
name = "orca",
about = "Orca Load Testing Utility
Orca works in a few steps.
1. Create an orca config which defines the targets you want to be able to setup and load test. See example_profiles/small/orca.toml
2. (Optional) preprocess an anonymised 389-ds access log (created from an external tool) into an orca data set.
3. 'orca setup' the kanidm/389-ds instance from the orca data set. You can see an example of this in example_profiles/small/data.json. This will reset the database, and add tons of entries etc. For example:
orca setup kanidm -p ./example_profiles/small/orca.toml
4. 'orca run' one of the metrics, based on that data set. For example:
orca run -p example_profiles/small/orca.toml kanidm search-basic
"
)]
enum OrcaOpt {
#[clap(name = "preprocess")]
PreProc(PreProcOpt),
#[clap(name = "setup")]
Setup(SetupOpt),
#[clap(name = "run")]
Run(RunOpt),
}