microsoft/openvmm

Public

mirrored from https://github.com/microsoft/openvmmAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
release/2411-fork

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

flowey/flowey_cli/src/var_db/single_json_file.rs

89lines · modecode

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! A dead simple runtime variable db, backed by a single JSON file.
5
6use anyhow::Context;
7use fs_err::File;
8use serde::Deserialize;
9use serde::Serialize;
10use std::collections::BTreeMap;
11use std::io::Seek;
12use std::io::Write;
13use std::path::Path;
14
15/// On-disk format for the var db
16#[derive(Serialize, Deserialize)]
17#[serde(transparent)]
18struct VarDb {
19 vars: BTreeMap<String, (bool, serde_json::Value)>,
20}
21
22/// Implements [`flowey_core::node::RuntimeVarDb`] backed by a JSON file.
23pub struct SingleJsonFileVarDb {
24 file: File,
25}
26
27impl SingleJsonFileVarDb {
28 pub fn new(backing_file: impl AsRef<Path>) -> anyhow::Result<Self> {
29 let backing_file = backing_file.as_ref();
30 let exists = backing_file.exists();
31 let mut file = fs_err::OpenOptions::new()
32 .read(true)
33 .write(true)
34 .create(true)
35 .open(backing_file)
36 .context("failed to open/create database file")?;
37
38 // seed the database file with an empty json map
39 if !exists {
40 eprintln!(
41 "seeding new empty database file: {}",
42 backing_file.display()
43 );
44 file.write_all(b"{}")?;
45 }
46
47 Ok(Self { file })
48 }
49
50 fn load_db(&mut self) -> VarDb {
51 self.file.rewind().unwrap();
52 serde_json::from_reader(&self.file).expect("corrupt runtime variable db")
53 }
54}
55
56impl flowey_core::node::RuntimeVarDb for SingleJsonFileVarDb {
57 fn try_get_var(&mut self, var_name: &str) -> Option<Vec<u8>> {
58 let db = self.load_db();
59 let (is_secret, val) = db.vars.get(var_name)?;
60 let val = val.to_string();
61 if *is_secret {
62 log::debug!("[db] read var: {} = <secret>", var_name);
63 } else {
64 log::debug!("[db] read var: {} = {}", var_name, val);
65 }
66 Some(val.into())
67 }
68
69 fn set_var(&mut self, var_name: &str, is_secret: bool, value: Vec<u8>) {
70 if is_secret {
71 log::debug!("[db] set var: {} = <secret>", var_name)
72 } else {
73 log::debug!(
74 "[db] set var: {} = {}",
75 var_name,
76 String::from_utf8_lossy(&value)
77 )
78 };
79 let mut db = self.load_db();
80 let existing = db.vars.insert(
81 var_name.into(),
82 (is_secret, serde_json::from_slice(&value).unwrap()),
83 );
84 assert!(existing.is_none()); // all vars are one-time-write
85 self.file.set_len(0).unwrap();
86 self.file.rewind().unwrap();
87 serde_json::to_writer(&self.file, &db).expect("failed to write to db JSON");
88 }
89}
90