arcs_ctf_yaml_parser/deploy/
mod.rs1pub mod error;
2pub mod structs;
3
4
5
6use serde_yaml::Value as YamlValue;
7use std::path::PathBuf;
8use std::str::FromStr;
9
10use crate::structs::get_type;
11use crate::Flop;
12
13use self::{
14 error::{DeployOptionsError, DeploymentTargetOptionsError, ExposeError, BuildError},
15 structs::{DeployOptions, DeployTarget, NetworkProtocol},
16};
17
18
19const DEFAULT_REPLICAS: u8 = 1;
20
21pub fn parse_expose(expose: &str) -> Result<NetworkProtocol, ExposeError> {
22
23 let (port, protocol) = expose
24 .split_once('/')
25 .ok_or_else(|| ExposeError::BadFormat(expose.to_string()))?;
26
27 let (port, protocol_is_tcp) = (
28 port.parse::<u32>(),
29 match protocol {
30 "udp" => Ok(false),
31 "tcp" => Ok(true),
32 _ => Err(()),
33 },
34 );
35
36 match (port, protocol_is_tcp) {
37 (Ok(port), Ok(protocol_is_tcp)) => Ok(if protocol_is_tcp {
38 NetworkProtocol::Tcp(port)
39 } else {
40 NetworkProtocol::Udp(port)
41 }),
42 (port, protocol_is_tcp) => Err(ExposeError::BadParts {
43 data: expose.to_string(),
44 port: port.is_err(),
45 protocol: protocol_is_tcp.is_err(),
46 }),
47 }
48}
49
50pub fn parse_deploy_target(value: &YamlValue) -> Result<DeployTarget, DeploymentTargetOptionsError> {
51 let mapping = value.as_mapping().ok_or_else(|| DeploymentTargetOptionsError::BadBaseType(get_type(value)))?;
52
53
54 let expose = mapping
55 .get("expose")
56 .and_then(YamlValue::as_str)
57 .map_or(Err(ExposeError::Missing), parse_expose);
58
59
60 let build = 'path_block: {
61 let Some(value) = mapping.get("src") else {
62 break 'path_block Ok(PathBuf::from("."))
63 };
64
65 let Some(string) = value.as_str() else {
66 break 'path_block Err(BuildError::BadType(get_type(value)))
67 };
68
69 let Ok(path) = PathBuf::from_str(string) else {
70 break 'path_block Err(BuildError::NotPath(string.to_string()))
71 };
72
73 if !path.is_relative() {
74 break 'path_block Err(BuildError::NotRelative(path));
75 }
76
77 Ok(path)
78 };
79
80 let replicas = mapping.get("replicas").map(|replicas_val| {
81 replicas_val
82 .as_u64()
83 .map(u8::try_from)
84 .and_then(Result::ok)
85 .ok_or_else(|| get_type(replicas_val))
86 }).flop();
87
88 match (expose, replicas, build) {
89 (Ok(expose), Ok(replicas), Ok(build)) => Ok(DeployTarget {
90 expose,
91 replicas: replicas.unwrap_or(DEFAULT_REPLICAS),
92 build,
93 }),
94 (expose, replicas, build) => Err(DeploymentTargetOptionsError::Parts {
95 expose: expose.err(),
96 replicas_invalid: replicas.err(),
97 build: build.err(),
98 })
99 }
100
101}
102
103pub fn parse_deploy(value: &YamlValue) -> Result<DeployOptions, DeployOptionsError> {
104 let mapping = value.as_mapping().ok_or_else(|| DeployOptionsError::BadBaseType(get_type(value)))?;
105
106 let web = mapping
107 .get("web")
108 .map(parse_deploy_target)
109 .flop();
110
111 let admin = mapping
112 .get("admin")
113 .map(parse_deploy_target)
114 .flop();
115
116 let nc = mapping
117 .get("nc")
118 .map(parse_deploy_target)
119 .flop();
120
121 match (web, admin, nc) {
122 (Ok(web), Ok(admin), Ok(nc)) => Ok(DeployOptions { web, admin, nc }),
123 (web, admin, nc) => Err(DeployOptionsError::Parts {
124 web: Box::new(web.err()),
125 admin: Box::new(admin.err()),
126 nc: Box::new(nc.err()),
127 })
128 }
129}
130