omicron_zone_package/
target.rs

1// This Source Code Form is subject to the terms of the Mozilla Public
2// License, v. 2.0. If a copy of the MPL was not distributed with this
3// file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
5use crate::package::Package;
6use serde::Deserialize;
7use serde::Serialize;
8use std::collections::BTreeMap;
9
10/// Describes what platform and configuration we're trying to deploy on.
11///
12/// For flexibility, this is an arbitrary key-value map without any attached
13/// semantics to particular keys. Those semantics are provided by the consumers
14/// of this tooling within omicron.
15#[derive(Clone, Debug, Default, PartialEq, Deserialize, Serialize)]
16#[serde(transparent)]
17pub struct TargetMap(pub BTreeMap<String, String>);
18
19impl TargetMap {
20    // Returns true if this target should include the package.
21    pub(crate) fn includes_package(&self, pkg: &Package) -> bool {
22        let valid_targets = if let Some(targets) = &pkg.only_for_targets {
23            // If targets are specified for the packages, filter them.
24            targets
25        } else {
26            // If no targets are specified, assume the package should be
27            // included by default.
28            return true;
29        };
30
31        // For each of the targets permitted by the package, check if
32        // the current target matches.
33        for (k, v) in &valid_targets.0 {
34            let target_value = if let Some(target_value) = self.0.get(k) {
35                target_value
36            } else {
37                return false;
38            };
39
40            if target_value != v {
41                return false;
42            };
43        }
44        true
45    }
46}
47
48impl std::fmt::Display for TargetMap {
49    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
50        for (key, value) in &self.0 {
51            write!(f, "{}={} ", key, value)?;
52        }
53        Ok(())
54    }
55}
56
57#[derive(thiserror::Error, Debug)]
58pub enum TargetParseError {
59    #[error("Cannot parse key-value pair out of '{0}'")]
60    MissingEquals(String),
61}
62
63impl std::str::FromStr for TargetMap {
64    type Err = TargetParseError;
65
66    fn from_str(s: &str) -> Result<Self, Self::Err> {
67        let kvs = s
68            .split_whitespace()
69            .map(|kv| {
70                kv.split_once('=')
71                    .ok_or_else(|| TargetParseError::MissingEquals(kv.to_string()))
72                    .map(|(k, v)| (k.to_string(), v.to_string()))
73            })
74            .collect::<Result<BTreeMap<String, String>, _>>()?;
75        Ok(TargetMap(kvs))
76    }
77}