WIP: Generic activation program #9
7 changed files with 58 additions and 9 deletions
|
@ -28,7 +28,7 @@ use super::{
|
|||
host::Local as LocalHost,
|
||||
key::{Key, UploadAt as UploadKeyAt},
|
||||
ColmenaError, ColmenaResult, CopyDirection, CopyOptions, Hive, Host, NodeConfig, NodeName,
|
||||
Profile, ProfileDerivation, RebootOptions,
|
||||
Profile, ProfileDerivation, RebootOptions, StorePath,
|
||||
};
|
||||
|
||||
/// A deployment.
|
||||
|
@ -637,7 +637,18 @@ impl Deployment {
|
|||
}
|
||||
}
|
||||
|
||||
host.activate(&profile_r, arc_self.goal).await?;
|
||||
let activation_program: &StorePath =
|
||||
&arc_self.hive
|
||||
.get_registry_config()
|
||||
.await?
|
||||
.systems
|
||||
.get(target.config.system_type.as_ref().unwrap_or(&"nixos".to_owned()))
|
||||
.expect(&format!("System type {} does not exists",
|
||||
target.config.system_type.as_ref().unwrap_or(&"nixos".to_owned())
|
||||
))
|
||||
.activation_program;
|
||||
|
||||
host.activate(&profile_r, arc_self.goal, activation_program).await?;
|
||||
|
||||
job.success_with_message(arc_self.goal.success_str().to_string())?;
|
||||
|
||||
|
|
|
@ -258,6 +258,12 @@ with builtins; rec {
|
|||
type = types.functionTo types.unspecified;
|
||||
default = _: {};
|
||||
};
|
||||
activationProgram = lib.mkOption {
|
||||
description = mdDoc ''
|
||||
Program to execute at activation time.
|
||||
'';
|
||||
type = types.path;
|
||||
};
|
||||
};
|
||||
};
|
||||
registryOptions = { lib, ... }: let
|
||||
|
|
|
@ -78,7 +78,12 @@ impl Host for Local {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
async fn activate(&mut self, profile: &Profile, goal: Goal) -> ColmenaResult<()> {
|
||||
async fn activate(
|
||||
&mut self,
|
||||
profile: &Profile,
|
||||
goal: Goal,
|
||||
activation_program: &StorePath,
|
||||
) -> ColmenaResult<()> {
|
||||
if !goal.requires_activation() {
|
||||
return Err(ColmenaError::Unsupported);
|
||||
}
|
||||
|
@ -91,7 +96,9 @@ impl Host for Local {
|
|||
}
|
||||
|
||||
let command = {
|
||||
let activation_command = profile.activation_command(goal).unwrap();
|
||||
let activation_command = profile
|
||||
.activation_command(goal, activation_program)
|
||||
.unwrap();
|
||||
self.make_privileged_command(&activation_command)
|
||||
};
|
||||
|
||||
|
|
|
@ -128,6 +128,7 @@ pub trait Host: Send + Sync + std::fmt::Debug {
|
|||
profile: &Profile,
|
||||
goal: Goal,
|
||||
copy_options: CopyOptions,
|
||||
activation_program: Option<&StorePath>,
|
||||
) -> ColmenaResult<()> {
|
||||
self.copy_closure(
|
||||
profile.as_store_path(),
|
||||
|
@ -137,7 +138,12 @@ pub trait Host: Send + Sync + std::fmt::Debug {
|
|||
.await?;
|
||||
|
||||
if goal.requires_activation() {
|
||||
self.activate(profile, goal).await?;
|
||||
self.activate(
|
||||
profile,
|
||||
goal,
|
||||
activation_program.expect("Unknown activation program"),
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
@ -171,7 +177,12 @@ pub trait Host: Send + Sync + std::fmt::Debug {
|
|||
///
|
||||
/// The profile must already exist on the host. You should probably use deploy instead.
|
||||
#[allow(unused_variables)]
|
||||
async fn activate(&mut self, profile: &Profile, goal: Goal) -> ColmenaResult<()> {
|
||||
async fn activate(
|
||||
&mut self,
|
||||
profile: &Profile,
|
||||
goal: Goal,
|
||||
activation_program: &StorePath,
|
||||
) -> ColmenaResult<()> {
|
||||
Err(ColmenaError::Unsupported)
|
||||
}
|
||||
|
||||
|
|
|
@ -90,7 +90,12 @@ impl Host for Ssh {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
async fn activate(&mut self, profile: &Profile, goal: Goal) -> ColmenaResult<()> {
|
||||
async fn activate(
|
||||
&mut self,
|
||||
profile: &Profile,
|
||||
goal: Goal,
|
||||
activation_program: &StorePath,
|
||||
) -> ColmenaResult<()> {
|
||||
if !goal.requires_activation() {
|
||||
return Err(ColmenaError::Unsupported);
|
||||
}
|
||||
|
@ -101,7 +106,9 @@ impl Host for Ssh {
|
|||
self.run_command(set_profile).await?;
|
||||
}
|
||||
|
||||
let activation_command = profile.activation_command(goal).unwrap();
|
||||
let activation_command = profile
|
||||
.activation_command(goal, activation_program)
|
||||
.unwrap();
|
||||
let v: Vec<&str> = activation_command.iter().map(|s| &**s).collect();
|
||||
let command = self.ssh(&v);
|
||||
self.run_command(command).await
|
||||
|
|
|
@ -101,6 +101,9 @@ pub struct MetaConfig {
|
|||
pub struct SystemTypeConfig {
|
||||
#[serde(rename = "supportsDeployment")]
|
||||
pub supports_deployment: bool,
|
||||
|
||||
#[serde(rename = "activationProgram")]
|
||||
pub activation_program: StorePath,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Validate, Deserialize)]
|
||||
|
|
|
@ -26,7 +26,11 @@ impl Profile {
|
|||
}
|
||||
|
||||
/// Returns the command to activate this profile.
|
||||
pub fn activation_command(&self, goal: Goal) -> Option<Vec<String>> {
|
||||
pub fn activation_command(
|
||||
&self,
|
||||
goal: Goal,
|
||||
activation_program: &StorePath,
|
||||
) -> Option<Vec<String>> {
|
||||
if let Some(goal) = goal.as_str() {
|
||||
let path = self.as_path().join("bin/switch-to-configuration");
|
||||
let switch_to_configuration = path
|
||||
|
|
Loading…
Reference in a new issue