treefile: allow ${releasever} in more keys
Besides allowing ${releasever}, only do the substitution as the final pass after merging the treefiles for all the keys (currently ${basearch} and ${releasever}) instead of doing it per parse. This way we have the expected semantics where one could do: ``` include: "fedora-coreos.yaml" releasever: "42" ``` and have that releasever used. Fixes #1809 Signed-off-by: Rafael Fonseca <r4f4rfs@gmail.com> Closes: #1848 Approved by: cgwalters
This commit is contained in:
parent
d0f90ca4dd
commit
c94bd08b02
10
rust/Cargo.lock
generated
10
rust/Cargo.lock
generated
@ -216,6 +216,14 @@ name = "encode_unicode"
|
||||
version = "0.3.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "envsubst"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "failure"
|
||||
version = "0.1.5"
|
||||
@ -631,6 +639,7 @@ dependencies = [
|
||||
"c_utf8 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"curl 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"envsubst 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gio-sys 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glib 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -937,6 +946,7 @@ dependencies = [
|
||||
"checksum dtoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6d301140eb411af13d3115f9a562c85cc6b541ade9dfa314132244aaee7489dd"
|
||||
"checksum either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5527cfe0d098f36e3f8839852688e63c8fff1c90b2b405aef730615f9a7bcf7b"
|
||||
"checksum encode_unicode 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "90b2c9496c001e8cb61827acdefad780795c42264c137744cae6f7d9e3450abd"
|
||||
"checksum envsubst 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "13cf19a8d534c83456ea13365a1935810a39f0e43bf1ec9371077e1966da396a"
|
||||
"checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2"
|
||||
"checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1"
|
||||
"checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82"
|
||||
|
@ -23,6 +23,7 @@ c_utf8 = "0.1.0"
|
||||
systemd = "0.4.0"
|
||||
indicatif = "0.11.0"
|
||||
lazy_static = "1.1.0"
|
||||
envsubst = "0.1.0"
|
||||
|
||||
[lib]
|
||||
name = "rpmostree_rust"
|
||||
|
@ -130,19 +130,6 @@ fn treefile_parse_stream<R: io::Read>(
|
||||
.into());
|
||||
}
|
||||
|
||||
// Substitute ${basearch}
|
||||
treefile.treeref = match (basearch, treefile.treeref.take()) {
|
||||
(Some(basearch), Some(treeref)) => {
|
||||
let mut varsubsts = HashMap::new();
|
||||
varsubsts.insert("basearch".to_string(), basearch.to_string());
|
||||
Some(
|
||||
utils::varsubst(&treeref, &varsubsts)
|
||||
.map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, e.to_string()))?,
|
||||
)
|
||||
}
|
||||
(_, v) => v,
|
||||
};
|
||||
|
||||
// Special handling for packages, since we allow whitespace within items.
|
||||
// We also canonicalize bootstrap_packages to packages here so it's
|
||||
// easier to append the basearch packages after.
|
||||
@ -410,7 +397,8 @@ impl Treefile {
|
||||
basearch: Option<&str>,
|
||||
workdir: openat::Dir,
|
||||
) -> Fallible<Box<Treefile>> {
|
||||
let parsed = treefile_parse_recurse(filename, basearch, 0)?;
|
||||
let mut parsed = treefile_parse_recurse(filename, basearch, 0)?;
|
||||
parsed.config = parsed.config.substitute_vars()?;
|
||||
Treefile::validate_config(&parsed.config)?;
|
||||
let dfd = openat::Dir::open(filename.parent().unwrap())?;
|
||||
let (rojig_name, rojig_spec) = if let Some(rojig) = parsed.config.rojig.as_ref() {
|
||||
@ -718,6 +706,39 @@ impl TreeComposeConfig {
|
||||
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
/// Look for use of ${variable} and replace it by its proper value
|
||||
fn substitute_vars(mut self) -> Fallible<Self> {
|
||||
let mut substvars: collections::HashMap<String, String> = collections::HashMap::new();
|
||||
// Substitute ${basearch} and ${releasever}
|
||||
if let Some(arch) = &self.basearch {
|
||||
substvars.insert("basearch".to_string(), arch.clone());
|
||||
}
|
||||
if let Some(releasever) = &self.releasever {
|
||||
substvars.insert("releasever".to_string(), releasever.clone());
|
||||
}
|
||||
envsubst::validate_vars(&substvars)?;
|
||||
|
||||
macro_rules! substitute_field {
|
||||
( $field:ident ) => {{
|
||||
if let Some(value) = self.$field.take() {
|
||||
self.$field = if envsubst::is_templated(&value) {
|
||||
match envsubst::substitute(value, &substvars) {
|
||||
Ok(s) => Some(s),
|
||||
Err(e) => return Err(e),
|
||||
}
|
||||
} else {
|
||||
Some(value)
|
||||
}
|
||||
}
|
||||
}};
|
||||
};
|
||||
substitute_field!(treeref);
|
||||
substitute_field!(automatic_version_prefix);
|
||||
substitute_field!(mutate_os_release);
|
||||
|
||||
Ok(self)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@ -753,8 +774,9 @@ packages-s390x:
|
||||
#[test]
|
||||
fn basic_valid() {
|
||||
let mut input = io::BufReader::new(VALID_PRELUDE.as_bytes());
|
||||
let treefile =
|
||||
let mut treefile =
|
||||
treefile_parse_stream(InputFormat::YAML, &mut input, Some(ARCH_X86_64)).unwrap();
|
||||
treefile = treefile.substitute_vars().unwrap();
|
||||
assert!(treefile.treeref.unwrap() == "exampleos/x86_64/blah");
|
||||
assert!(treefile.packages.unwrap().len() == 5);
|
||||
}
|
||||
@ -785,8 +807,9 @@ remove-files:
|
||||
#[test]
|
||||
fn basic_js_valid() {
|
||||
let mut input = io::BufReader::new(VALID_PRELUDE_JS.as_bytes());
|
||||
let treefile =
|
||||
let mut treefile =
|
||||
treefile_parse_stream(InputFormat::JSON, &mut input, Some(ARCH_X86_64)).unwrap();
|
||||
treefile = treefile.substitute_vars().unwrap();
|
||||
assert!(treefile.treeref.unwrap() == "exampleos/x86_64/blah");
|
||||
assert!(treefile.packages.unwrap().len() == 5);
|
||||
}
|
||||
@ -794,7 +817,8 @@ remove-files:
|
||||
#[test]
|
||||
fn basic_valid_noarch() {
|
||||
let mut input = io::BufReader::new(VALID_PRELUDE.as_bytes());
|
||||
let treefile = treefile_parse_stream(InputFormat::YAML, &mut input, None).unwrap();
|
||||
let mut treefile = treefile_parse_stream(InputFormat::YAML, &mut input, None).unwrap();
|
||||
treefile = treefile.substitute_vars().unwrap();
|
||||
assert!(treefile.treeref.unwrap() == "exampleos/x86_64/blah");
|
||||
assert!(treefile.packages.unwrap().len() == 3);
|
||||
}
|
||||
@ -802,7 +826,9 @@ remove-files:
|
||||
fn append_and_parse(append: &'static str) -> TreeComposeConfig {
|
||||
let buf = VALID_PRELUDE.to_string() + append;
|
||||
let mut input = io::BufReader::new(buf.as_bytes());
|
||||
treefile_parse_stream(InputFormat::YAML, &mut input, Some(ARCH_X86_64)).unwrap()
|
||||
let treefile =
|
||||
treefile_parse_stream(InputFormat::YAML, &mut input, Some(ARCH_X86_64)).unwrap();
|
||||
treefile.substitute_vars().unwrap()
|
||||
}
|
||||
|
||||
fn test_invalid(data: &'static str) {
|
||||
@ -817,6 +843,31 @@ remove-files:
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn basic_valid_releasever() {
|
||||
let buf = r###"
|
||||
ref: "exampleos/${basearch}/${releasever}"
|
||||
releasever: 30
|
||||
automatic-version-prefix: ${releasever}
|
||||
mutate-os-release: ${releasever}
|
||||
"###;
|
||||
let mut input = io::BufReader::new(buf.as_bytes());
|
||||
let mut treefile =
|
||||
treefile_parse_stream(InputFormat::YAML, &mut input, Some(ARCH_X86_64)).unwrap();
|
||||
treefile = treefile.substitute_vars().unwrap();
|
||||
assert!(treefile.treeref.unwrap() == "exampleos/x86_64/30");
|
||||
assert!(treefile.releasever.unwrap() == "30");
|
||||
assert!(treefile.automatic_version_prefix.unwrap() == "30");
|
||||
assert!(treefile.mutate_os_release.unwrap() == "30");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_valid_no_releasever() {
|
||||
let treefile = append_and_parse("automatic_version_prefix: ${releasever}");
|
||||
assert!(treefile.releasever == None);
|
||||
assert!(treefile.automatic_version_prefix.unwrap() == "${releasever}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn basic_valid_legacy() {
|
||||
let treefile = append_and_parse(
|
||||
|
Loading…
Reference in New Issue
Block a user