public inbox for pmg-devel@lists.proxmox.com
 help / color / mirror / Atom feed
From: Fabian Ebner <f.ebner@proxmox.com>
To: pmg-devel@lists.proxmox.com
Subject: [pmg-devel] [PATCH pmg-rs 2/2] add bindings for proxmox-apt
Date: Tue, 13 Jul 2021 10:04:11 +0200	[thread overview]
Message-ID: <20210713080413.26662-3-f.ebner@proxmox.com> (raw)
In-Reply-To: <20210713080413.26662-1-f.ebner@proxmox.com>

Signed-off-by: Fabian Ebner <f.ebner@proxmox.com>
---
 Cargo.toml              |   4 +
 Makefile                |   7 ++
 debian/control          |   2 +
 src/apt/mod.rs          |   1 +
 src/apt/repositories.rs | 159 ++++++++++++++++++++++++++++++++++++++++
 src/lib.rs              |   1 +
 6 files changed, 174 insertions(+)
 create mode 100644 src/apt/mod.rs
 create mode 100644 src/apt/repositories.rs

diff --git a/Cargo.toml b/Cargo.toml
index d942daa..553d5eb 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -24,5 +24,9 @@ serde_json = "1.0"
 perlmod = { version = "0.5.2", features = [ "exporter" ] }
 #perlmod = { path = "../perlmod/perlmod", features = [ "exporter" ] }
 
+proxmox = { version = "0.11.5", default-features = false }
+
 proxmox-acme-rs = { version = "0.2.2", features = ["client"] }
 #proxmox-acme-rs = { path = "../proxmox-acme-rs", features = ["client"] }
+
+proxmox-apt = "0.4.0"
diff --git a/Makefile b/Makefile
index 9d475c7..67eeb15 100644
--- a/Makefile
+++ b/Makefile
@@ -14,8 +14,12 @@ DEBS=$(MAIN_DEB) $(DBGSYM_DEB)
 
 DESTDIR=
 
+PM_DIRS := \
+	PMG/RS/APT
+
 PM_FILES := \
 	PMG/RS/Acme.pm \
+	PMG/RS/APT/Repositories.pm \
 	PMG/RS/CSR.pm
 
 ifeq ($(BUILD_MODE), release)
@@ -40,6 +44,9 @@ install: target/release/libpmg_rs.so
 	install -d -m755 $(DESTDIR)$(PERL_INSTALLVENDORARCH)/auto
 	install -m644 target/release/libpmg_rs.so $(DESTDIR)$(PERL_INSTALLVENDORARCH)/auto/libpmg_rs.so
 	install -d -m755 $(DESTDIR)$(PERL_INSTALLVENDORLIB)/PMG/RS
+	for i in $(PM_DIRS); do \
+	  install -d -m755 $(DESTDIR)$(PERL_INSTALLVENDORLIB)/$$i; \
+	done
 	for i in $(PM_FILES); do \
 	  install -m644 $$i $(DESTDIR)$(PERL_INSTALLVENDORLIB)/$$i; \
 	done
diff --git a/debian/control b/debian/control
index 677a28d..fe5dad6 100644
--- a/debian/control
+++ b/debian/control
@@ -5,6 +5,8 @@ Maintainer: Proxmox Support Team <support@proxmox.com>
 Build-Depends: debhelper (>= 12),
                librust-curl-dev,
                librust-proxmox-acme-rs+client-dev,
+               librust-proxmox-apt-dev,
+               librust-proxmox-dev,
                librust-perlmod-macro-dev,
                librust-anyhow-dev,
                librust-openssl-dev,
diff --git a/src/apt/mod.rs b/src/apt/mod.rs
new file mode 100644
index 0000000..574c1a7
--- /dev/null
+++ b/src/apt/mod.rs
@@ -0,0 +1 @@
+mod repositories;
diff --git a/src/apt/repositories.rs b/src/apt/repositories.rs
new file mode 100644
index 0000000..81552e3
--- /dev/null
+++ b/src/apt/repositories.rs
@@ -0,0 +1,159 @@
+#[perlmod::package(name = "PMG::RS::APT::Repositories", lib = "pmg_rs")]
+mod export {
+    use std::convert::TryInto;
+
+    use anyhow::{bail, Error};
+    use serde::{Deserialize, Serialize};
+
+    use proxmox_apt::repositories::{
+        APTRepositoryFile, APTRepositoryFileError, APTRepositoryHandle, APTRepositoryInfo,
+        APTStandardRepository,
+    };
+
+    #[derive(Deserialize, Serialize)]
+    #[serde(rename_all = "kebab-case")]
+    /// Result for the repositories() function
+    pub struct RepositoriesResult {
+        /// Successfully parsed files.
+        pub files: Vec<APTRepositoryFile>,
+
+        /// Errors for files that could not be parsed or read.
+        pub errors: Vec<APTRepositoryFileError>,
+
+        /// Common digest for successfully parsed files.
+        pub digest: String,
+
+        /// Additional information/warnings about repositories.
+        pub infos: Vec<APTRepositoryInfo>,
+
+        /// Standard repositories and their configuration status.
+        pub standard_repos: Vec<APTStandardRepository>,
+    }
+
+    #[derive(Deserialize, Serialize)]
+    #[serde(rename_all = "kebab-case")]
+    /// For changing an existing repository.
+    pub struct ChangeProperties {
+        /// Whether the repository should be enabled or not.
+        pub enabled: Option<bool>,
+    }
+
+    /// Get information about configured and standard repositories.
+    #[export]
+    pub fn repositories() -> Result<RepositoriesResult, Error> {
+        let (files, errors, digest) = proxmox_apt::repositories::repositories()?;
+        let digest = proxmox::tools::digest_to_hex(&digest);
+
+        let infos = proxmox_apt::repositories::check_repositories(&files)?;
+        let standard_repos = proxmox_apt::repositories::standard_repositories("pmg", &files);
+
+        Ok(RepositoriesResult {
+            files,
+            errors,
+            digest,
+            infos,
+            standard_repos,
+        })
+    }
+
+    /// Add the repository identified by the `handle`.
+    /// If the repository is already configured, it will be set to enabled.
+    ///
+    /// The `digest` parameter asserts that the configuration has not been modified.
+    #[export]
+    pub fn add_repository(handle: &str, digest: Option<&str>) -> Result<(), Error> {
+        let (mut files, errors, current_digest) = proxmox_apt::repositories::repositories()?;
+
+        let handle: APTRepositoryHandle = handle.try_into()?;
+
+        if let Some(digest) = digest {
+            let expected_digest = proxmox::tools::hex_to_digest(digest)?;
+            if expected_digest != current_digest {
+                bail!("detected modified configuration - file changed by other user? Try again.");
+            }
+        }
+
+        // check if it's already configured first
+        for file in files.iter_mut() {
+            for repo in file.repositories.iter_mut() {
+                if repo.is_referenced_repository(handle, "pmg") {
+                    if repo.enabled {
+                        return Ok(());
+                    }
+
+                    repo.set_enabled(true);
+                    file.write()?;
+
+                    return Ok(());
+                }
+            }
+        }
+
+        let (repo, path) = proxmox_apt::repositories::get_standard_repository(handle, "pmg")?;
+
+        if let Some(error) = errors.iter().find(|error| error.path == path) {
+            bail!(
+                "unable to parse existing file {} - {}",
+                error.path,
+                error.error,
+            );
+        }
+
+        if let Some(file) = files.iter_mut().find(|file| file.path == path) {
+            file.repositories.push(repo);
+
+            file.write()?;
+        } else {
+            let mut file = match APTRepositoryFile::new(&path)? {
+                Some(file) => file,
+                None => bail!("invalid path - {}", path),
+            };
+
+            file.repositories.push(repo);
+
+            file.write()?;
+        }
+
+        Ok(())
+    }
+
+    /// Change the properties of the specified repository.
+    ///
+    /// The `digest` parameter asserts that the configuration has not been modified.
+    #[export]
+    pub fn change_repository(
+        path: &str,
+        index: usize,
+        options: ChangeProperties,
+        digest: Option<&str>,
+    ) -> Result<(), Error> {
+        let (mut files, errors, current_digest) = proxmox_apt::repositories::repositories()?;
+
+        if let Some(digest) = digest {
+            let expected_digest = proxmox::tools::hex_to_digest(digest)?;
+            if expected_digest != current_digest {
+                bail!("detected modified configuration - file changed by other user? Try again.");
+            }
+        }
+
+        if let Some(error) = errors.iter().find(|error| error.path == path) {
+            bail!("unable to parse file {} - {}", error.path, error.error);
+        }
+
+        if let Some(file) = files.iter_mut().find(|file| file.path == path) {
+            if let Some(repo) = file.repositories.get_mut(index) {
+                if let Some(enabled) = options.enabled {
+                    repo.set_enabled(enabled);
+                }
+
+                file.write()?;
+            } else {
+                bail!("invalid index - {}", index);
+            }
+        } else {
+            bail!("invalid path - {}", path);
+        }
+
+        Ok(())
+    }
+}
diff --git a/src/lib.rs b/src/lib.rs
index 9822106..47e61b5 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,2 +1,3 @@
 pub mod acme;
+pub mod apt;
 pub mod csr;
-- 
2.30.2





  parent reply	other threads:[~2021-07-13  8:04 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-07-13  8:04 [pmg-devel] [PATCH-SERIES pmg-rs/pmg-api/pmg-gui] add APT repositories API/UI Fabian Ebner
2021-07-13  8:04 ` [pmg-devel] [PATCH pmg-rs 1/2] bump perlmod dependency Fabian Ebner
2021-07-13  8:04 ` Fabian Ebner [this message]
2021-07-13  8:04 ` [pmg-devel] [PATCH pmg-api 1/1] api: apt: add calls for repositories Fabian Ebner
2021-07-13  8:04 ` [pmg-devel] [PATCH pmg-gui 1/1] add panel for APT repositories Fabian Ebner
2021-07-13 12:33 ` [pmg-devel] applied-series: [PATCH-SERIES pmg-rs/pmg-api/pmg-gui] add APT repositories API/UI Thomas Lamprecht

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210713080413.26662-3-f.ebner@proxmox.com \
    --to=f.ebner@proxmox.com \
    --cc=pmg-devel@lists.proxmox.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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