|
9 | 9 |
|
10 | 10 | use kdl::{KdlDocument, KdlNode}; |
11 | 11 |
|
12 | | -use crate::spec::{RawRestart, RawSpec, RawTask}; |
| 12 | +use crate::spec::{RawResource, RawRestart, RawSpec, RawTask}; |
13 | 13 |
|
14 | 14 | /// Parse a KDL document into zero or more raw specs (one per top-level `agent` node). |
15 | 15 | pub(crate) fn parse_kdl(text: &str) -> anyhow::Result<Vec<RawSpec>> { |
@@ -84,6 +84,10 @@ fn agent_node_to_raw(node: &KdlNode) -> anyhow::Result<RawSpec> { |
84 | 84 | "retired" => raw.retired = arg_bool(child), |
85 | 85 | "keep" => raw.keep = arg_bool(child), |
86 | 86 | "restart" => raw.restart = Some(restart_node_to_raw(child)), |
| 87 | + "resource" => { |
| 88 | + let (name, resource) = resource_node_to_raw(child)?; |
| 89 | + raw.resource.insert(name, resource)?; |
| 90 | + } |
87 | 91 | "command" => raw.command = arg_string(child), |
88 | 92 | "argv" => raw.argv = Some(argv(child)?), |
89 | 93 | "ding" => raw.ding = true, |
@@ -111,6 +115,60 @@ fn agent_node_to_raw(node: &KdlNode) -> anyhow::Result<RawSpec> { |
111 | 115 | Ok(raw) |
112 | 116 | } |
113 | 117 |
|
| 118 | +fn resource_node_to_raw(node: &KdlNode) -> anyhow::Result<(String, RawResource)> { |
| 119 | + if node.children().is_some() { |
| 120 | + anyhow::bail!("resource binding cannot have children"); |
| 121 | + } |
| 122 | + |
| 123 | + let mut name = None; |
| 124 | + let mut tag = None; |
| 125 | + let mut uri = None; |
| 126 | + for entry in node.entries() { |
| 127 | + let Some(property) = entry.name() else { |
| 128 | + if name.is_some() { |
| 129 | + anyhow::bail!("resource binding accepts exactly one positional name"); |
| 130 | + } |
| 131 | + name = entry.value().as_string().map(String::from); |
| 132 | + if name.is_none() { |
| 133 | + anyhow::bail!("resource binding needs a string name"); |
| 134 | + } |
| 135 | + continue; |
| 136 | + }; |
| 137 | + |
| 138 | + let property = property.value(); |
| 139 | + let value = entry.value().as_string().map(String::from); |
| 140 | + match property { |
| 141 | + "_tag" => { |
| 142 | + if tag.is_some() { |
| 143 | + anyhow::bail!("resource binding has duplicate `_tag`"); |
| 144 | + } |
| 145 | + tag = value; |
| 146 | + if tag.is_none() { |
| 147 | + anyhow::bail!("resource binding needs string `_tag`"); |
| 148 | + } |
| 149 | + } |
| 150 | + "uri" => { |
| 151 | + if uri.is_some() { |
| 152 | + anyhow::bail!("resource binding has duplicate `uri`"); |
| 153 | + } |
| 154 | + uri = value; |
| 155 | + if uri.is_none() { |
| 156 | + anyhow::bail!("resource binding needs string `uri`"); |
| 157 | + } |
| 158 | + } |
| 159 | + other => anyhow::bail!("resource binding has unsupported property `{other}`"), |
| 160 | + } |
| 161 | + } |
| 162 | + |
| 163 | + Ok(( |
| 164 | + name.ok_or_else(|| anyhow::anyhow!("resource binding needs a string name"))?, |
| 165 | + RawResource { |
| 166 | + tag: tag.ok_or_else(|| anyhow::anyhow!("resource binding needs string `_tag`"))?, |
| 167 | + uri: uri.ok_or_else(|| anyhow::anyhow!("resource binding needs string `uri`"))?, |
| 168 | + }, |
| 169 | + )) |
| 170 | +} |
| 171 | + |
114 | 172 | fn restart_node_to_raw(node: &KdlNode) -> RawRestart { |
115 | 173 | let mut r = RawRestart::default(); |
116 | 174 | let Some(children) = node.children() else { |
|
0 commit comments