From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from firstgate.proxmox.com (firstgate.proxmox.com [212.224.123.68]) by lore.proxmox.com (Postfix) with ESMTPS id 0A55E1FF15C for ; Wed, 13 Nov 2024 10:06:50 +0100 (CET) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id 02DB41086F; Wed, 13 Nov 2024 10:06:49 +0100 (CET) From: Christoph Heiss To: pve-devel@lists.proxmox.com Date: Wed, 13 Nov 2024 10:06:36 +0100 Message-ID: <20241113090639.436459-1-c.heiss@proxmox.com> X-Mailer: git-send-email 2.47.0 MIME-Version: 1.0 X-SPAM-LEVEL: Spam detection results: 0 AWL 0.029 Adjusted score from AWL reputation of From: address BAYES_00 -1.9 Bayes spam probability is 0 to 1% DMARC_MISSING 0.1 Missing DMARC policy KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment RCVD_IN_VALIDITY_CERTIFIED_BLOCKED 0.001 ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. RCVD_IN_VALIDITY_RPBL_BLOCKED 0.001 ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. RCVD_IN_VALIDITY_SAFE_BLOCKED 0.001 ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record Subject: [pve-devel] [PATCH installer] fetch-answer: add `$fetchinfo` meta-field to HTTP POST payload X-BeenThere: pve-devel@lists.proxmox.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Proxmox VE development discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: Proxmox VE development discussion Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Errors-To: pve-devel-bounces@lists.proxmox.com Sender: "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 "." 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 --- 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 { - 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 { + 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 { + 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