public inbox for pve-devel@lists.proxmox.com
 help / color / mirror / Atom feed
* [pve-devel] [PATCH installer] fetch-answer: add `$fetchinfo` meta-field to HTTP POST payload
@ 2024-11-13  9:06 Christoph Heiss
  0 siblings, 0 replies; only message in thread
From: Christoph Heiss @ 2024-11-13  9:06 UTC (permalink / raw)
  To: pve-devel

This adds a metadata-field `$fetchinfo` containing a single key
`version` (for now) to the POST payload json, indicating which schema
version (and thus structure) this document uses.

The version field follows the format "<major>.<minor>" and applies
semantic versioning meaning for both the major and minor number. A patch
version is left out here, as it doesn't make much sense in this context.

Works in the same manner as the post-hook does it [0]. Useful to have it
for this too, as we might change/expand this structure too in the
future.

In the resulting JSON, this will look like this:
{
    "$fetchinfo": {
	"version": "1.0"
    },
    "product": ..,
    ..
}

[0] https://lore.proxmox.com/pve-devel/20241112145405.929194-1-c.heiss@proxmox.com/

Signed-off-by: Christoph Heiss <c.heiss@proxmox.com>
---
 proxmox-auto-installer/src/sysinfo.rs         |  5 --
 proxmox-fetch-answer/Cargo.toml               |  2 +
 .../src/fetch_plugins/http.rs                 | 65 ++++++++++++++++++-
 3 files changed, 66 insertions(+), 6 deletions(-)

diff --git a/proxmox-auto-installer/src/sysinfo.rs b/proxmox-auto-installer/src/sysinfo.rs
index 0a6aaf2..a45ae59 100644
--- a/proxmox-auto-installer/src/sysinfo.rs
+++ b/proxmox-auto-installer/src/sysinfo.rs
@@ -41,11 +41,6 @@ impl SysInfo {
         let info = Self::get()?;
         Ok(serde_json::to_string_pretty(&info)?)
     }
-
-    pub fn as_json() -> Result<String> {
-        let info = Self::get()?;
-        Ok(serde_json::to_string(&info)?)
-    }
 }
 
 #[derive(Debug, Serialize)]
diff --git a/proxmox-fetch-answer/Cargo.toml b/proxmox-fetch-answer/Cargo.toml
index 50f3da3..23bd094 100644
--- a/proxmox-fetch-answer/Cargo.toml
+++ b/proxmox-fetch-answer/Cargo.toml
@@ -15,4 +15,6 @@ anyhow.workspace = true
 log.workspace = true
 proxmox-auto-installer.workspace = true
 proxmox-installer-common = { workspace = true, features = ["http"] }
+serde = { workspace = true, features = ["derive"] }
+serde_json.workspace = true
 toml.workspace = true
diff --git a/proxmox-fetch-answer/src/fetch_plugins/http.rs b/proxmox-fetch-answer/src/fetch_plugins/http.rs
index 4317430..fb9ffc8 100644
--- a/proxmox-fetch-answer/src/fetch_plugins/http.rs
+++ b/proxmox-fetch-answer/src/fetch_plugins/http.rs
@@ -1,5 +1,6 @@
 use anyhow::{bail, Result};
 use log::info;
+use serde::Serialize;
 use std::{
     fs::{self, read_to_string},
     process::Command,
@@ -28,6 +29,67 @@ static DHCP_URL_OPTION: &str = "proxmox-auto-installer-manifest-url";
 static DHCP_CERT_FP_OPTION: &str = "proxmox-auto-installer-cert-fingerprint";
 static DHCP_LEASE_FILE: &str = "/var/lib/dhcp/dhclient.leases";
 
+/// Metadata of the HTTP POST payload, such as schema version of the document.
+#[derive(Serialize)]
+#[serde(rename_all = "kebab-case")]
+struct HttpFetchInfoMeta {
+    /// major.minor version describing the schema version of this document, in a semanticy-version
+    /// way.
+    ///
+    /// major: Incremented for incompatible/breaking API changes, e.g. removing an existing
+    /// field.
+    /// minor: Incremented when adding functionality in a backwards-compatible matter, e.g.
+    /// adding a new field.
+    version: String,
+}
+
+impl HttpFetchInfoMeta {
+    const SCHEMA_VERSION: &str = "1.0";
+}
+
+impl Default for HttpFetchInfoMeta {
+    fn default() -> Self {
+        Self {
+            version: Self::SCHEMA_VERSION.to_owned(),
+        }
+    }
+}
+
+/// All data sent as request payload with the answerfile fetch POST request.
+///
+/// NOTE: The format is versioned through `fetch_meta.version` (`$fetchinfo.version` in the
+/// resulting JSON), ensure you update it when this struct or any of its members gets modified.
+#[derive(Serialize)]
+#[serde(rename_all = "kebab-case")]
+struct HttpFetchPayload {
+    /// Metadata for the answerfile fetch payload
+    // This field is prefixed by `$` on purpose, to indicate that it is document metadata and not
+    // part of the actual content itself. (E.g. JSON Schema uses a similar naming scheme)
+    #[serde(rename = "$fetchinfo")]
+    fetch_meta: HttpFetchInfoMeta,
+    /// Information about the running system, flattened into this structure directly.
+    #[serde(flatten)]
+    sysinfo: SysInfo,
+}
+
+impl HttpFetchPayload {
+    /// Retrieves the required information from the system and constructs the
+    /// full payload including meta data.
+    fn get() -> Result<Self> {
+        Ok(Self {
+            fetch_meta: HttpFetchInfoMeta::default(),
+            sysinfo: SysInfo::get()?,
+        })
+    }
+
+    /// Retrieves the required information from the system and constructs the
+    /// full payload including meta data, serialized as JSON.
+    pub fn as_json() -> Result<String> {
+        let info = Self::get()?;
+        Ok(serde_json::to_string(&info)?)
+    }
+}
+
 pub struct FetchFromHTTP;
 
 impl FetchFromHTTP {
@@ -65,7 +127,8 @@ impl FetchFromHTTP {
         }
 
         info!("Gathering system information.");
-        let payload = SysInfo::as_json()?;
+        let payload = HttpFetchPayload::as_json()?;
+
         info!("Sending POST request to '{answer_url}'.");
         let answer =
             proxmox_installer_common::http::post(&answer_url, fingerprint.as_deref(), payload)?;
-- 
2.47.0



_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2024-11-13  9:06 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-11-13  9:06 [pve-devel] [PATCH installer] fetch-answer: add `$fetchinfo` meta-field to HTTP POST payload Christoph Heiss

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal