首页 > 解决方案 > 如何在 Rust 中更新具有动态属性的 yaml 文件?

问题描述

考虑一个包含当前内容的 yaml 文件:

namespaces:
  production:

helmRepos:
  stable: "https://kubernetes-charts.storage.googleapis.com"

context: monitoring

apps:
  datadog:
    enabled: true
    namespace: production
    chart: stable/datadog
    version: "1.38.7"
    valuesFile: "values.yaml"

我想以编程方式更新version此文件中属性的值。 最好的方法是什么?

让它有点困难的是我认为我不能使用结构来反序列化/序列化这个文件,因为例如下面的键helmRepos可以是任何东西。

我查看了serde_yaml板条箱,但我无法弄清楚如何更改具有不可预测键的文件中的值,然后将其序列化回来。我也是 Rust 的初学者,因此我可能会遗漏一些明显的东西。

标签: serializationrustyaml

解决方案


如果你想用来serde修改你的文件,基本的做法是反序列化、修改、重新序列化。这将从您的 yaml 文件中删除所有注释和自定义格式,例如空行,所以我不确定这是您想要的方法。

使用serde_yaml,有不同的选择来实现这个目标。在我看来,最简单的是使用Value类型,它可以表示任意的 yaml 值:

const DOC: &str = r#"namespaces:
  production:

helmRepos:
  stable: "https://kubernetes-charts.storage.googleapis.com"

context: monitoring

apps:
  datadog:
    enabled: true
    namespace: production
    chart: stable/datadog
    version: "1.38.7"
    valuesFile: "values.yaml"
"#;

fn main() {
    let mut value: serde_yaml::Value = serde_yaml::from_str(DOC).unwrap();
    *value
        .get_mut("apps")
        .unwrap()
        .get_mut("datadog")
        .unwrap()
        .get_mut("version")
        .unwrap() = "1.38.8".into();
    serde_yaml::to_writer(std::io::stdout(), &value).unwrap();
}

操场

您可能想要适当的错误处理而不是unwrap()到处使用。如果您对使用unwrap()上述代码感到满意,可以简化为

let mut value: serde_yaml::Value = serde_yaml::from_str(DOC).unwrap();
value["apps"]["datadog"]["version"] = "1.38.8".into();
serde_yaml::to_writer(std::io::stdout(), &value).unwrap();

如果您不想丢失评论和空行,事情会变得更加棘手。实现该目标的正确解决方案是使用yaml_rustcrate 解析文件并确定要更改的行。然而,如果你不需要你的代码是健壮的,你可能会使用一些特别的方法来找到正确的行。


推荐阅读