1use crate::contract::API_VERSION;
2use serde::{Deserialize, Serialize};
3use std::collections::BTreeMap;
4use std::path::PathBuf;
5
6#[derive(Clone, Debug, PartialEq, Eq)]
7pub enum ConfigSource {
8 NixInstallable(String),
9 CanonicalJson(PathBuf),
10}
11
12#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
13#[serde(rename_all = "camelCase", deny_unknown_fields)]
14pub struct ValidationReport {
15 pub api_version: String,
16 pub kind: ValidationReportKind,
17 pub metadata: ValidationReportMetadata,
18 pub spec: ValidationReportSpec,
19}
20
21#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
22pub enum ValidationReportKind {
23 ValidationReport,
24}
25
26#[derive(Clone, Debug, Default, Deserialize, Serialize, PartialEq, Eq)]
27#[serde(deny_unknown_fields)]
28pub struct ValidationReportMetadata {}
29
30#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
31#[serde(rename_all = "camelCase", deny_unknown_fields)]
32pub struct ValidationReportSpec {
33 pub resource_count: usize,
34}
35
36impl ValidationReport {
37 pub(super) fn new(resource_count: usize) -> Self {
38 Self {
39 api_version: API_VERSION.to_string(),
40 kind: ValidationReportKind::ValidationReport,
41 metadata: ValidationReportMetadata {},
42 spec: ValidationReportSpec { resource_count },
43 }
44 }
45}
46
47#[derive(Clone, Debug, PartialEq, Eq)]
48pub struct ValidateRequest {
49 pub source: ConfigSource,
50 pub working_root: PathBuf,
51 pub selectors: Vec<String>,
52}
53
54#[derive(Clone, Debug, PartialEq, Eq)]
55pub struct PlanRequest {
56 pub source: ConfigSource,
57 pub working_root: PathBuf,
59 pub selectors: Vec<String>,
60 pub lifecycle_intent: Option<crate::host_lifecycle::LifecycleIntent>,
61 pub install_mode: Option<crate::host_lifecycle::InstallMode>,
63 pub enrollment_strategy: Option<crate::host_lifecycle::EnrollmentStrategy>,
66 pub reactivate: bool,
69 pub reenroll: bool,
72 pub convert_from: Option<String>,
74 pub offline: bool,
76 pub host_identity_action: Option<crate::host_lifecycle::HostIdentityAction>,
79 pub endpoint_overrides: BTreeMap<String, String>,
82}
83
84#[derive(Clone, Debug, PartialEq, Eq)]
85pub struct InfoRequest {
86 pub source: ConfigSource,
87 pub target: String,
88 pub observe_ip: bool,
91 pub wait: bool,
93}
94
95#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
96#[serde(rename_all = "camelCase", deny_unknown_fields)]
97pub struct InfoReport {
98 pub hostname: String,
99 #[serde(skip_serializing_if = "Option::is_none")]
100 pub ip: Option<String>,
101 pub user: String,
102 pub class: String,
103 pub system: String,
104 pub vmid: String,
105 pub provider: String,
106}
107
108#[derive(Clone, Debug, PartialEq, Eq)]
109pub struct ApplyRequest {
110 pub plan: PathBuf,
111 pub run_id: Option<String>,
112 pub approval_evidence: Option<PathBuf>,
113 pub parallel: usize,
114}
115
116#[derive(Clone, Debug, PartialEq, Eq)]
117pub struct ArtifactBuildRequest {
118 pub selector: String,
119 pub source: ConfigSource,
120 pub working_root: PathBuf,
121 pub output_root: PathBuf,
122 pub parallel: usize,
123}
124
125#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
126#[serde(rename_all = "camelCase", deny_unknown_fields)]
127pub struct ArtifactBuildOutput {
128 pub role: String,
129 pub path: String,
130}
131
132#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
133#[serde(rename_all = "camelCase", deny_unknown_fields)]
134pub struct ArtifactBuildReport {
135 pub plan_path: String,
136 pub manifest_path: String,
137 pub run_id: String,
138 pub applied_action_count: usize,
139 pub outputs: Vec<ArtifactBuildOutput>,
140}
141
142#[derive(Clone, Debug, PartialEq, Eq)]
143pub struct CreateApprovalRequest {
144 pub plan: PathBuf,
145 pub principal: String,
146 pub expires_at_unix: Option<u64>,
148}
149
150#[derive(Clone, Debug, PartialEq, Eq)]
151pub struct ValidateApprovalRequest {
152 pub plan: PathBuf,
153 pub approval_evidence: PathBuf,
154}
155
156#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
157#[serde(rename_all = "camelCase", deny_unknown_fields)]
158pub struct ApplyReport {
159 pub run_id: String,
160 pub applied_action_count: usize,
161 pub status: ApplyStatus,
162}
163
164#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
166#[serde(rename_all = "camelCase")]
167pub struct PlanDisplay {
168 #[serde(flatten)]
169 pub plan: crate::plan::PlanEnvelope,
170 pub plan_digest: String,
171}
172
173#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
174#[serde(rename_all = "camelCase", deny_unknown_fields)]
175pub struct CancelRunReport {
176 pub run_id: String,
177 pub status: String,
178}
179
180impl CancelRunReport {
181 pub fn requested(run_id: impl Into<String>) -> Self {
182 Self { run_id: run_id.into(), status: "cancellation-requested".to_string() }
183 }
184}
185
186#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
187#[serde(rename_all = "camelCase", deny_unknown_fields)]
188pub struct MonitorRunReport {
189 pub run_id: String,
190 pub final_status: String,
191 pub action_status: BTreeMap<String, String>,
192 pub errors: Vec<String>,
193}
194
195#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
196#[serde(rename_all = "kebab-case")]
197pub enum ApplyStatus {
198 Succeeded,
199}
200
201#[derive(Clone, Debug, PartialEq, Eq)]
202pub struct VerifyRequest {
203 pub source: ConfigSource,
204 pub working_root: PathBuf,
206 pub selectors: Vec<String>,
207 pub verbose: bool,
208}
209
210#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
211#[serde(rename_all = "camelCase", deny_unknown_fields)]
212pub struct VerificationReport {
213 pub api_version: String,
214 pub kind: VerificationReportKind,
215 pub metadata: VerificationReportMetadata,
216 pub spec: VerificationReportSpec,
217}
218
219#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
220pub enum VerificationReportKind {
221 VerificationReport,
222}
223
224#[derive(Clone, Debug, Default, Deserialize, Serialize, PartialEq, Eq)]
225#[serde(deny_unknown_fields)]
226pub struct VerificationReportMetadata {}
227
228#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
229#[serde(rename_all = "camelCase", deny_unknown_fields)]
230pub struct VerificationReportSpec {
231 pub resource_count: usize,
232 pub status: VerificationStatus,
233}
234
235#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
236#[serde(rename_all = "kebab-case")]
237pub enum VerificationStatus {
238 Passed,
239}
240
241impl VerificationReport {
242 pub(super) fn passed(resource_count: usize) -> Self {
243 Self {
244 api_version: API_VERSION.to_string(),
245 kind: VerificationReportKind::VerificationReport,
246 metadata: VerificationReportMetadata {},
247 spec: VerificationReportSpec { resource_count, status: VerificationStatus::Passed },
248 }
249 }
250}
251
252#[derive(Clone, Debug, PartialEq, Eq)]
253pub struct CaptureRequest {
254 pub source: ConfigSource,
255 pub selectors: Vec<String>,
256 pub output_root: Option<PathBuf>,
257}
258
259#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
260#[serde(rename_all = "camelCase", deny_unknown_fields)]
261pub struct CaptureReport {
262 pub status: CaptureStatus,
263 pub outcomes: Vec<CaptureOutcome>,
264}
265
266#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
267#[serde(rename_all = "kebab-case")]
268pub enum CaptureStatus {
269 Complete,
270 Incomplete,
271}
272
273#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
274#[serde(rename_all = "camelCase", deny_unknown_fields)]
275pub struct CaptureOutcome {
276 pub node: String,
277 pub artifact: String,
278 pub status: CaptureOutcomeStatus,
279}
280
281#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
282#[serde(rename_all = "camelCase")]
283pub enum CaptureOutcomeStatus {
284 Captured,
285 Skipped { reason: String },
286 Failed { error: String },
287}
288
289impl CaptureReport {
290 pub fn failed_count(&self) -> usize {
291 self
292 .outcomes
293 .iter()
294 .filter(|outcome| matches!(outcome.status, CaptureOutcomeStatus::Failed { .. }))
295 .count()
296 }
297}
298
299#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
300#[serde(rename_all = "camelCase", deny_unknown_fields)]
301pub struct OperationReport {
302 pub api_version: String,
303 pub kind: OperationReportKind,
304 pub metadata: OperationReportMetadata,
305 pub spec: OperationReportSpec,
306}
307
308#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
309pub enum OperationReportKind {
310 OperationReport,
311}
312
313#[derive(Clone, Debug, Default, Deserialize, Serialize, PartialEq, Eq)]
314#[serde(deny_unknown_fields)]
315pub struct OperationReportMetadata {}
316
317#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
318#[serde(rename_all = "camelCase", deny_unknown_fields)]
319pub struct OperationReportSpec {
320 pub operation: String,
321 pub resource_count: usize,
322 pub action_count: usize,
323 pub highest_risk: Option<String>,
324 pub status: String,
325}
326
327impl OperationReport {
328 pub fn new(
329 operation: impl Into<String>,
330 resource_count: usize,
331 action_count: usize,
332 highest_risk: Option<String>,
333 status: impl Into<String>,
334 ) -> Self {
335 Self {
336 api_version: API_VERSION.to_string(),
337 kind: OperationReportKind::OperationReport,
338 metadata: OperationReportMetadata {},
339 spec: OperationReportSpec {
340 operation: operation.into(),
341 resource_count,
342 action_count,
343 highest_risk,
344 status: status.into(),
345 },
346 }
347 }
348}