mistletoe_api/v1alpha1/
mistresult.rs1use anyhow::anyhow;
2use indexmap::IndexMap;
3use serde::{Serialize, Deserialize};
4
5pub type MistResult = anyhow::Result<MistOutput>;
11
12pub fn serialize_result(result: MistResult) -> Result<String, serde_yaml::Error> {
14 serde_yaml::to_string(&MistResultLayout::from(result))
15}
16
17pub fn deserialize_result(result_str: &str) -> MistResult {
19 serde_yaml::from_str::<MistResultLayout>(result_str)?.into()
20}
21
22#[derive(Clone, PartialEq, Debug)]
24pub struct MistOutput {
25 message: Option<String>,
26
27 files: IndexMap<String, String>,
32}
33
34impl MistOutput {
35 pub fn new() -> Self {
37 Self {
38 message: None,
39 files: IndexMap::new(),
40 }
41 }
42
43 pub fn set_message(&mut self, message: String) {
46 self.message = Some(message);
47 }
48
49
50 pub fn with_message(mut self, message: String) -> Self {
55 self.set_message(message);
56 self
57 }
58
59 pub fn set_file(&mut self, filename: String, content: String) {
61 self.files.insert(filename, content);
62 }
63
64 pub fn with_file(mut self, filename: String, content: String) -> Self {
68 self.set_file(filename, content);
69 self
70 }
71
72 pub fn get_message(&self) -> &Option<String> {
74 &self.message
75 }
76
77 pub fn get_files(&self) -> &IndexMap<String, String> {
79 &self.files
80 }
81}
82
83#[derive(Serialize, Deserialize)]
84#[serde(rename_all = "camelCase")]
85struct MistResultLayout {
86 api_version: String,
87 kind: String,
88 data: MistResultLayoutData,
89}
90
91#[derive(Serialize, Deserialize)]
92struct MistResultLayoutData {
93 result: String,
94 #[serde(default, skip_serializing_if = "Option::is_none")]
95 message: Option<String>,
96 #[serde(default, skip_serializing_if = "IndexMap::is_empty")]
97 files: IndexMap<String, String>,
98}
99
100impl From<MistResult> for MistResultLayout {
101 fn from(result: MistResult) -> Self {
102 Self {
103 api_version: "mistletoe.dev/v1alpha1".to_string(),
104 kind: "MistResult".to_string(),
105 data: match result {
106 Ok(output) => MistResultLayoutData {
107 result: "Ok".to_string(),
108 message: output.message,
109 files: output.files,
110 },
111 Err(e) => MistResultLayoutData {
112 result: "Err".to_string(),
113 message: Some(e.to_string()),
114 files: IndexMap::new(),
115 },
116 }
117 }
118 }
119}
120
121impl Into<MistResult> for MistResultLayout {
122 fn into(self) -> MistResult {
123 match self.data.result.as_str() {
124 "Ok" => MistResult::Ok(MistOutput {
125 message: self.data.message,
126 files: self.data.files,
127 }),
128 "Err" => MistResult::Err(match self.data.message {
129 Some(message) => anyhow!(message),
130 None => anyhow!("package failed without a message"),
131 }),
132 s => MistResult::Err(anyhow!("package result format error: `data.result` must either be \"Ok\" or \"Err\", found {}", s)),
133 }
134 }
135}
136
137#[cfg(test)]
138mod tests {
139 use super::*;
140 use indoc::indoc;
141
142 #[test]
143 fn test_mistresult_ok() {
144 let expected_yaml = indoc!{"
145 apiVersion: mistletoe.dev/v1alpha1
146 kind: MistResult
147 data:
148 result: Ok
149 message: 'warning: nothing went wrong'
150 files:
151 namespace.yaml: |
152 apiVersion: v1
153 kind: Namespace
154 metadata:
155 name: my-namespace"};
156
157 let mistoutput = MistOutput::new()
158 .with_message("warning: nothing went wrong".to_string())
159 .with_file("namespace.yaml".to_string(), indoc!("
160 apiVersion: v1
161 kind: Namespace
162 metadata:
163 name: my-namespace")
164 .to_string());
165
166 let yaml = serialize_result(Ok(mistoutput.clone())).unwrap();
167 assert_eq!(expected_yaml, yaml);
168
169 let mistresult_parsed = deserialize_result(&yaml).unwrap();
170 assert_eq!(mistoutput, mistresult_parsed);
171 }
172
173 #[test]
174 fn test_mistresult_err() {
175 let expected_yaml: &str = indoc!{"
176 apiVersion: mistletoe.dev/v1alpha1
177 kind: MistResult
178 data:
179 result: Err
180 message: 'error: something went wrong'"};
181
182 let err_string = "error: something went wrong";
183 let yaml = serialize_result(Err(anyhow!(err_string.to_string()))).unwrap();
184 assert_eq!(expected_yaml, yaml);
185
186 let mistresult_parsed = deserialize_result(&yaml);
187 assert_eq!(err_string, mistresult_parsed.err().unwrap().to_string());
188 }
189}