add proxmox-section-config crate

Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
This commit is contained in:
Wolfgang Bumiller 2021-10-07 13:39:10 +02:00
parent 41f3fdfeb9
commit f35dbbd651
8 changed files with 143 additions and 50 deletions

View File

@ -8,6 +8,7 @@ members = [
"proxmox-lang",
"proxmox-router",
"proxmox-schema",
"proxmox-section-config",
"proxmox-sortable-macro",
"proxmox-tfa",
"proxmox-time",

View File

@ -9,6 +9,7 @@ CRATES = \
proxmox-lang \
proxmox-router \
proxmox-schema \
proxmox-section-config \
proxmox-sortable-macro \
proxmox-tfa \
proxmox-time \

View File

@ -0,0 +1,19 @@
[package]
name = "proxmox-section-config"
version = "1.0.0"
authors = ["Proxmox Support Team <support@proxmox.com>"]
edition = "2018"
license = "AGPL-3"
description = "proxmox schema based section config format parsing"
exclude = [ "debian" ]
[dependencies]
anyhow = "1.0"
hex = "0.4"
serde = "1.0"
serde_json = "1.0"
proxmox-schema = { path = "../proxmox-schema", version = "1.0.0" }
# FIXME: remove!
proxmox-lang = { path = "../proxmox-lang", version = "1.0.0" }

View File

@ -0,0 +1,5 @@
rust-proxmox-section-config (1.0.0-1) stable; urgency=medium
* initial split out of `librust-proxmox-dev`
-- Proxmox Support Team <support@proxmox.com> Wed, 06 Oct 2021 11:04:36 +0200

View File

@ -0,0 +1,42 @@
Source: rust-proxmox-section-config
Section: rust
Priority: optional
Build-Depends: debhelper (>= 12),
dh-cargo (>= 24),
cargo:native <!nocheck>,
rustc:native <!nocheck>,
libstd-rust-dev <!nocheck>,
librust-anyhow-1+default-dev <!nocheck>,
librust-hex-0.4+default-dev <!nocheck>,
librust-proxmox-lang-1+default-dev <!nocheck>,
librust-proxmox-schema-1+default-dev <!nocheck>,
librust-serde-1+default-dev <!nocheck>,
librust-serde-json-1+default-dev <!nocheck>
Maintainer: Proxmox Support Team <support@proxmox.com>
Standards-Version: 4.5.1
Vcs-Git: git://git.proxmox.com/git/proxmox.git
Vcs-Browser: https://git.proxmox.com/?p=proxmox.git
Rules-Requires-Root: no
Package: librust-proxmox-section-config-dev
Architecture: any
Multi-Arch: same
Depends:
${misc:Depends},
librust-anyhow-1+default-dev,
librust-hex-0.4+default-dev,
librust-proxmox-lang-1+default-dev,
librust-proxmox-schema-1+default-dev,
librust-serde-1+default-dev,
librust-serde-json-1+default-dev
Provides:
librust-proxmox-section-config+default-dev (= ${binary:Version}),
librust-proxmox-section-config-1-dev (= ${binary:Version}),
librust-proxmox-section-config-1+default-dev (= ${binary:Version}),
librust-proxmox-section-config-1.0-dev (= ${binary:Version}),
librust-proxmox-section-config-1.0+default-dev (= ${binary:Version}),
librust-proxmox-section-config-1.0.0-dev (= ${binary:Version}),
librust-proxmox-section-config-1.0.0+default-dev (= ${binary:Version})
Description: Proxmox schema based section config format parsing - Rust source code
This package contains the source for the Rust proxmox-section-config crate,
packaged by debcargo for use with cargo and dh-cargo.

View File

@ -0,0 +1,16 @@
Copyright (C) 2021 Proxmox Server Solutions GmbH
This software is written by Proxmox Server Solutions GmbH <support@proxmox.com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.

View File

@ -0,0 +1,7 @@
overlay = "."
crate_src_path = ".."
maintainer = "Proxmox Support Team <support@proxmox.com>"
[source]
vcs_git = "git://git.proxmox.com/git/proxmox.git"
vcs_browser = "https://git.proxmox.com/?p=proxmox.git"

View File

@ -18,18 +18,18 @@
//! ...
//! ```
use anyhow::*;
use std::collections::HashMap;
use std::collections::HashSet;
use std::collections::VecDeque;
use anyhow::{bail, format_err, Error};
use serde::de::DeserializeOwned;
use serde::ser::Serialize;
use serde_json::{json, Value};
use super::schema::*;
use crate::try_block;
use proxmox_lang::try_block;
use proxmox_schema::format::{dump_properties, wrap_text, ParameterDisplayStyle};
use proxmox_schema::*;
/// Associates a section type name with a `Schema`.
pub struct SectionConfigPlugin {
@ -180,7 +180,7 @@ impl SectionConfigData {
let mut list: Vec<Value> = vec![];
let digest: Value = match digest {
Some(v) => crate::tools::digest_to_hex(v).into(),
Some(v) => hex::encode(v).into(),
None => Value::Null,
};
@ -294,62 +294,64 @@ impl SectionConfig {
/// plugins. Please note that `filename` is only used to improve
/// error messages.
pub fn write(&self, filename: &str, config: &SectionConfigData) -> Result<String, Error> {
try_block!({
let mut list = VecDeque::new();
self.write_do(config)
.map_err(|e: Error| format_err!("writing '{}' failed: {}", filename, e))
}
let mut done = HashSet::new();
fn write_do(&self, config: &SectionConfigData) -> Result<String, Error> {
let mut list = VecDeque::new();
for section_id in &config.order {
if config.sections.get(section_id) == None {
continue;
};
list.push_back(section_id);
done.insert(section_id);
let mut done = HashSet::new();
for section_id in &config.order {
if config.sections.get(section_id) == None {
continue;
};
list.push_back(section_id);
done.insert(section_id);
}
for section_id in config.sections.keys() {
if done.contains(section_id) {
continue;
};
list.push_back(section_id);
}
let mut raw = String::new();
for section_id in list {
let (type_name, section_config) = config.sections.get(section_id).unwrap();
let plugin = self.plugins.get(type_name).unwrap();
let id_schema = plugin.get_id_schema().unwrap_or(self.id_schema);
if let Err(err) = parse_simple_value(&section_id, &id_schema) {
bail!("syntax error in section identifier: {}", err.to_string());
}
if section_id.chars().any(|c| c.is_control()) {
bail!("detected unexpected control character in section ID.");
}
if let Err(err) = verify_json_object(section_config, plugin.properties) {
bail!("verify section '{}' failed - {}", section_id, err);
}
for section_id in config.sections.keys() {
if done.contains(section_id) {
continue;
};
list.push_back(section_id);
if !raw.is_empty() {
raw += "\n"
}
let mut raw = String::new();
raw += &(self.format_section_header)(type_name, section_id, section_config)?;
for section_id in list {
let (type_name, section_config) = config.sections.get(section_id).unwrap();
let plugin = self.plugins.get(type_name).unwrap();
let id_schema = plugin.get_id_schema().unwrap_or(self.id_schema);
if let Err(err) = parse_simple_value(&section_id, &id_schema) {
bail!("syntax error in section identifier: {}", err.to_string());
}
if section_id.chars().any(|c| c.is_control()) {
bail!("detected unexpected control character in section ID.");
}
if let Err(err) = verify_json_object(section_config, plugin.properties) {
bail!("verify section '{}' failed - {}", section_id, err);
}
if !raw.is_empty() {
raw += "\n"
}
raw += &(self.format_section_header)(type_name, section_id, section_config)?;
for (key, value) in section_config.as_object().unwrap() {
if let Some(id_property) = &plugin.id_property {
if id_property == key {
continue; // skip writing out id properties, they are in the section header
}
for (key, value) in section_config.as_object().unwrap() {
if let Some(id_property) = &plugin.id_property {
if id_property == key {
continue; // skip writing out id properties, they are in the section header
}
raw += &(self.format_section_content)(type_name, section_id, key, value)?;
}
raw += &(self.format_section_content)(type_name, section_id, key, value)?;
}
}
Ok(raw)
})
.map_err(|e: Error| format_err!("writing '{}' failed: {}", filename, e))
Ok(raw)
}
/// Parse configuration data.