Skip to content

Commit

Permalink
Fixes #23767: Make an install subcommand for the new rudder-package
Browse files Browse the repository at this point in the history
  • Loading branch information
Félix Dallidet committed Nov 22, 2023
1 parent bf227ca commit f5b6eca
Show file tree
Hide file tree
Showing 6 changed files with 134 additions and 14 deletions.
48 changes: 40 additions & 8 deletions relay/sources/rudder-package/src/archive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
use anyhow::{anyhow, bail, Context, Ok, Result};
use ar::Archive;
use core::fmt;
use log::debug;
use serde::{Deserialize, Serialize};
use std::{
fs::{self, *},
Expand All @@ -13,10 +14,12 @@ use std::{
};

use crate::{
cmd::CmdOutput,
database::{Database, InstalledPlugin},
plugin::Metadata,
versions::RudderVersion,
webapp_xml::WebappXml,
PACKAGES_DATABASE_PATH, PACKAGES_FOLDER, WEBAPP_XML_PATH,
PACKAGES_DATABASE_PATH, PACKAGES_FOLDER, RUDDER_VERSION_FILE, WEBAPP_XML_PATH,
};

#[derive(Serialize, Deserialize, PartialEq, Eq, Debug, Clone, Copy)]
Expand Down Expand Up @@ -76,7 +79,7 @@ pub struct Rpkg {
}

impl Rpkg {
fn from_path(path: &str) -> Result<Rpkg> {
pub fn from_path(path: &str) -> Result<Rpkg> {
let r = Rpkg {
path: String::from(path),
metadata: read_metadata(path).unwrap(),
Expand Down Expand Up @@ -154,6 +157,7 @@ impl Rpkg {
}

fn unpack_embedded_txz(&self, txz_name: &str, dst_path: &str) -> Result<(), anyhow::Error> {
debug!("Extracting archive '{}' in folder '{}'", txz_name, dst_path);
let dst = Path::new(dst_path);
// Loop over ar archive files
let mut archive = Archive::new(File::open(self.path.clone()).unwrap());
Expand Down Expand Up @@ -184,11 +188,22 @@ impl Rpkg {
Ok(current_database.is_installed(self.to_owned()))
}

pub fn install(&self) -> Result<()> {
let keys = self.metadata.content.keys().clone();
pub fn install(&self, force: bool) -> Result<()> {
debug!("Installing rpkg '{}'...", self.path);
// Verify webapp compatibility
let webapp_version = RudderVersion::from_path(RUDDER_VERSION_FILE)?;
if !(force
|| self
.metadata
.version
.rudder_version
.is_compatible(&webapp_version.to_string()))
{
bail!("This plugin was built for a Rudder '{}', it is incompatible with your current webapp version '{}'.", self.metadata.version.rudder_version, webapp_version)
}
// Verify that dependencies are installed
if let Some(d) = &self.metadata.depends {
if !d.are_installed() {
if !(force || d.are_installed()) {
bail!("Some dependencies are missing, install them before trying to install the plugin.")
}
}
Expand All @@ -198,6 +213,7 @@ impl Rpkg {
let install_or_upgrade: PackageScriptArg = PackageScriptArg::Install;
self.run_package_script(PackageScript::Preinst, install_or_upgrade)?;
// Extract archive content
let keys = self.metadata.content.keys().clone();
for txz_name in keys {
let dst = self.get_txz_dst(txz_name);
self.unpack_embedded_txz(txz_name, &dst)?
Expand All @@ -217,6 +233,7 @@ impl Rpkg {
let install_or_upgrade: PackageScriptArg = PackageScriptArg::Install;
self.run_package_script(PackageScript::Postinst, install_or_upgrade)?;
// Update the webapp xml file if the plugin contains one or more jar file
debug!("Enabling the associated jars if any");
match self.metadata.jar_files.clone() {
None => (),
Some(jars) => {
Expand All @@ -226,19 +243,34 @@ impl Rpkg {
}
}
}
// Restarting webapp
debug!("Install completed");
Ok(())
}

fn run_package_script(&self, script: PackageScript, arg: PackageScriptArg) -> Result<()> {
debug!(
"Running package script '{}' with args '{}' for rpkg '{}'...",
script, arg, self.path
);
let package_script_path = Path::new(PACKAGES_FOLDER)
.join(self.metadata.name.clone())
.join(script.to_string());
if !package_script_path.exists() {
debug!("Skipping as the script does not exist.");
return Ok(());
}
let _result = Command::new(package_script_path)
.arg(arg.to_string())
.output()?;
let mut binding = Command::new(package_script_path);
let cmd = binding.arg(arg.to_string());
let r = match CmdOutput::new(cmd) {
std::result::Result::Ok(a) => a,
Err(e) => {
bail!("Could not execute package script '{}'`n{}", script, e);
}
};
if !r.output.status.success() {
debug!("Package script execution return unexpected exit code.");
}
Ok(())
}
}
Expand Down
17 changes: 16 additions & 1 deletion relay/sources/rudder-package/src/cli.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: 2023 Normation SAS

use clap::Parser;
use clap::{Parser, Subcommand};

use crate::CONFIG_PATH;

Expand All @@ -15,4 +15,19 @@ pub struct Args {
/// Enable verbose logs
#[arg(short, long, default_value_t = false)]
pub debug: bool,

#[clap(subcommand)]
pub command: Command,
}

#[derive(Debug, Subcommand)]
pub enum Command {
Install {
#[clap(long, short = 'f', help = "Force installation of given plugin")]
force: bool,

#[clap()]
package: String,
},
List {},
}
2 changes: 2 additions & 0 deletions relay/sources/rudder-package/src/database.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use serde::{Deserialize, Serialize};

use super::archive::Rpkg;
use crate::plugin;
use log::debug;

#[derive(Serialize, Deserialize, PartialEq, Eq, Debug, Clone)]
pub struct Database {
Expand All @@ -23,6 +24,7 @@ impl Database {
}

pub fn write(path: &str, index: Database) -> Result<()> {
debug!("Updating the installed plugin database in '{}'", path);
let file = File::create(path)?;
let mut writer = BufWriter::new(file);
serde_json::to_writer_pretty(&mut writer, &index)
Expand Down
39 changes: 36 additions & 3 deletions relay/sources/rudder-package/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ mod webapp_xml;

use std::path::Path;

use crate::cli::Command;
use anyhow::{Context, Result};
use clap::Parser;
use log::{debug, error, LevelFilter};
Expand All @@ -29,6 +30,7 @@ const WEBAPP_XML_PATH: &str = "/opt/rudder/share/webapps/rudder.xml";
const PACKAGES_DATABASE_PATH: &str = "/var/rudder/packages/index.json";
const CONFIG_PATH: &str = "/opt/rudder/etc/rudder-pkg/rudder-pkg.conf";
const SIGNATURE_KEYRING_PATH: &str = "/opt/rudder/etc/rudder-pkg/rudder_plugins_key.gpg";
const RUDDER_VERSION_FILE: &str = "/opt/rudder/share/versions/rudder-server-version";

/// CLI entry point
pub fn run() -> Result<()> {
Expand All @@ -47,10 +49,41 @@ pub fn run() -> Result<()> {
debug!("Parsed CLI arguments: {args:?}");
let cfg = Configuration::read(Path::new(&args.config))
.with_context(|| format!("Reading configuration from '{}'", &args.config))?;
debug!("Parsed configuration: {cfg:?}");

let _repo = Repository::new(&cfg)?;
debug!("Parsed configuration: {cfg:?}");

error!("This command is not implemented");
match args.command {
Command::Install { force, package } => {
return action::install(force, package);
}
_ => {
error!("This command is not implemented");
}
}
Ok(())
}

pub mod action {
use anyhow::{bail, Result};

use crate::archive::Rpkg;
use crate::database::Database;
use crate::PACKAGES_DATABASE_PATH;
use std::path::Path;

pub fn install(force: bool, package: String) -> Result<()> {
let rpkg_path = if Path::new(&package).exists() {
package
} else {
bail!("TODO");
};
let rpkg = Rpkg::from_path(&rpkg_path)?;
rpkg.install(force)
}

pub fn list() -> Result<()> {
let db = Database::read(PACKAGES_DATABASE_PATH);
println!("Installed plugins:\n{:?}", db);
Ok(())
}
}
29 changes: 27 additions & 2 deletions relay/sources/rudder-package/src/versions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@
// SPDX-FileCopyrightText: 2023 Normation SAS

use core::fmt;
use std::{cmp::Ordering, fmt::Display, str::FromStr};
use std::{cmp::Ordering, fmt::Display, fs, str::FromStr};

use anyhow::{bail, Error, Result};
use log::debug;
use regex::Regex;
use serde::{de, Deserialize, Deserializer, Serialize, Serializer};

Expand Down Expand Up @@ -124,6 +125,23 @@ impl RudderVersion {
Err(_) => false,
}
}

pub fn from_path(path: &str) -> Result<Self, Error> {
let content = fs::read_to_string(path)?;
let re = Regex::new(r"rudder_version=(?<raw_rudder_version>.*)")?;
let caps = match re.captures(&content) {
None => bail!(
"'{}' does not look like a well formed Rudder version file.",
path
),
Some(c) => c,
};
debug!(
"Raw Rudder version read from '{}' file: '{}'.",
path, &caps["raw_rudder_version"]
);
RudderVersion::from_str(&caps["raw_rudder_version"])
}
}

impl FromStr for RudderVersion {
Expand All @@ -132,7 +150,7 @@ impl FromStr for RudderVersion {
fn from_str(raw: &str) -> Result<Self, Self::Err> {
let re = Regex::new(r"^(?<major>\d+)\.(?<minor>\d+)\.(?<patch>\d+)(?<mode>.*)$")?;
let caps = match re.captures(raw) {
None => bail!("Unparsable rudder version '{}'", raw),
None => bail!("Unparsable Rudder version '{}'", raw),
Some(c) => c,
};
let major: u32 = caps["major"].parse()?;
Expand Down Expand Up @@ -218,6 +236,12 @@ mod tests {

use super::*;

#[test]
fn test_rudder_version_from_path() {
let a = RudderVersion::from_path("./tests/versions/rudder-server-version").unwrap();
assert_eq!(a, RudderVersion::from_str("8.0.4~git202311160211").unwrap());
}

#[rstest]
#[case("7.0.0~alpha2", 7, 0, 0, "~alpha2")]
#[case("7.0.0", 7, 0, 0, "")]
Expand All @@ -234,6 +258,7 @@ mod tests {
assert_eq!(v.minor, e_minor);
assert_eq!(v.patch, e_patch);
assert_eq!(v.mode, RudderVersionMode::from_str(e_mode).unwrap());
assert_eq!(v.to_string(), raw);
}

#[rstest]
Expand Down
13 changes: 13 additions & 0 deletions relay/sources/rudder-package/tests/versions/rudder-server-version
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
rudder_version=8.0.4~git202311160211
main_version=8.0.4
release_step=8.0.4
nightly_tag=git202311160211
repository_version=8.0-nightly
git_ref=branches/rudder/8.0
rudder_commit=dd702432da9128de6a2fbc97490b10f202c443ba
rudder-techniques_commit=629a1c51002d736fa189a50c30dcaa6c972af1de
rudder-doc_commit=66ce25f3cff7185b12b20f90b8bcc6a225ff6f4f
rudder-packages_commit=baaf8b3b3e29cb668b5bac58e6f6c86c6bb59a43
rudder-agent_commit=609b412e77ca84b8c1266658eeed4085f854274d
ncf_commit=ffaff0c270b7c715ac2ae3db0cc1f5134cec8005
rudder-api-client_commit=e1db11d7ba9d753a70c2f579120941955cdb0f3d

0 comments on commit f5b6eca

Please sign in to comment.