Skip to content

Commit

Permalink
add(task): Allow editing environment variables
Browse files Browse the repository at this point in the history
  • Loading branch information
Nukesor committed Dec 1, 2024
1 parent 8cc7893 commit 161dc10
Show file tree
Hide file tree
Showing 10 changed files with 231 additions and 45 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ TLDR: The new task state representation is more verbose but significantly cleane
- Allow `pueue status` to order tasks by `enqueue_at`. [#554](https://github.com/Nukesor/pueue/issues/554)
- Added Windows service on Windows to allow a true daemon experience. [#344](https://github.com/Nukesor/pueue/issues/344) [#567](https://github.com/Nukesor/pueue/pull/567)
- Add `queued_count` and `stashed_count` to callback template variables. This allows users to fire callbacks when whole groups are finished. [#578](https://github.com/Nukesor/pueue/issues/578)
- Add new subcommand to set or unset environment variables for tasks. [#503](https://github.com/Nukesor/pueue/issues/503)

### Fixed

Expand Down
34 changes: 32 additions & 2 deletions pueue/src/client/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use pueue_lib::network::message::Signal;

use super::commands::WaitTargetStatus;

#[derive(Parser, Debug)]
#[derive(Parser, Debug, Clone)]
pub enum SubCommand {
#[command(
about = "Enqueue a task for execution.\n\
Expand Down Expand Up @@ -278,6 +278,12 @@ pub enum SubCommand {
task_ids: Vec<usize>,
},

#[command(about = "Use this to add or remove environment variables from tasks.")]
Env {
#[command(subcommand)]
cmd: EnvCommand,
},

#[command(about = "Use this to add or remove groups.\n\
By default, this will simply display all known groups.")]
Group {
Expand Down Expand Up @@ -492,7 +498,31 @@ https://github.com/Nukesor/pueue/issues/350#issue-1359083118"
},
}

#[derive(Parser, Debug)]
#[derive(Parser, Debug, Clone)]
pub enum EnvCommand {
/// Set a variable for a specific task's environment.
Set {
/// The id of the task for which the variable should be set.
task_id: usize,

Check warning on line 506 in pueue/src/client/cli.rs

View check run for this annotation

Codecov / codecov/patch

pueue/src/client/cli.rs#L506

Added line #L506 was not covered by tests

/// The name of the environment variable to set.
key: String,

Check warning on line 509 in pueue/src/client/cli.rs

View check run for this annotation

Codecov / codecov/patch

pueue/src/client/cli.rs#L509

Added line #L509 was not covered by tests

/// The value of the environment variable to set.
value: String,

Check warning on line 512 in pueue/src/client/cli.rs

View check run for this annotation

Codecov / codecov/patch

pueue/src/client/cli.rs#L512

Added line #L512 was not covered by tests
},

/// Remove a specific variable from a task's environment.
Unset {
/// The id of the task for which the variable should be set.
task_id: usize,

Check warning on line 518 in pueue/src/client/cli.rs

View check run for this annotation

Codecov / codecov/patch

pueue/src/client/cli.rs#L518

Added line #L518 was not covered by tests

/// The name of the environment variable to set.
key: String,

Check warning on line 521 in pueue/src/client/cli.rs

View check run for this annotation

Codecov / codecov/patch

pueue/src/client/cli.rs#L521

Added line #L521 was not covered by tests
},
}

#[derive(Parser, Debug, Clone)]
pub enum GroupCommand {
/// Add a group by name.
Add {
Expand Down
81 changes: 46 additions & 35 deletions pueue/src/client/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ use crate::client::cli::{CliArguments, ColorChoice, GroupCommand, SubCommand};
use crate::client::commands::*;
use crate::client::display::*;

use super::cli::EnvCommand;

/// This struct contains the base logic for the client.
/// The client is responsible for connecting to the daemon, sending instructions
/// and interpreting their responses.
Expand Down Expand Up @@ -383,7 +385,7 @@ impl Client {
/// This function is pretty large, but it consists mostly of simple conversions
/// of [SubCommand] variant to a [Message] variant.
fn get_message_from_opt(&self) -> Result<Message> {
Ok(match &self.subcommand {
Ok(match self.subcommand.clone() {
SubCommand::Add {
command,
working_directory,
Expand All @@ -406,7 +408,7 @@ impl Client {
let mut command = command.clone();
// The user can request to escape any special shell characters in all parameter strings before
// we concatenated them to a single string.
if *escape {
if escape {
command = command
.iter()
.map(|parameter| shell_escape::escape(Cow::from(parameter)).into_owned())
Expand All @@ -418,20 +420,20 @@ impl Client {
path,
// Catch the current environment for later injection into the task's process.
envs: HashMap::from_iter(vars()),
start_immediately: *start_immediately,
stashed: *stashed,
group: group_or_default(group),
enqueue_at: *delay_until,
dependencies: dependencies.to_vec(),
priority: priority.to_owned(),
label: label.clone(),
print_task_id: *print_task_id,
start_immediately,
stashed,
group: group_or_default(&group),
enqueue_at: delay_until,
dependencies,
priority,
label,
print_task_id,
}
.into()
}
SubCommand::Remove { task_ids } => {
if self.settings.client.show_confirmation_questions {
self.handle_user_confirmation("remove", task_ids)?;
self.handle_user_confirmation("remove", &task_ids)?;

Check warning on line 436 in pueue/src/client/client.rs

View check run for this annotation

Codecov / codecov/patch

pueue/src/client/client.rs#L436

Added line #L436 was not covered by tests
}
Message::Remove(task_ids.clone())
}
Expand All @@ -441,19 +443,19 @@ impl Client {
all,
delay_until,
} => {
let selection = selection_from_params(*all, group, task_ids);
let selection = selection_from_params(all, &group, &task_ids);

Check warning on line 446 in pueue/src/client/client.rs

View check run for this annotation

Codecov / codecov/patch

pueue/src/client/client.rs#L446

Added line #L446 was not covered by tests
StashMessage {
tasks: selection,
enqueue_at: *delay_until,
enqueue_at: delay_until,

Check warning on line 449 in pueue/src/client/client.rs

View check run for this annotation

Codecov / codecov/patch

pueue/src/client/client.rs#L449

Added line #L449 was not covered by tests
}
.into()
}
SubCommand::Switch {
task_id_1,
task_id_2,
} => SwitchMessage {
task_id_1: *task_id_1,
task_id_2: *task_id_2,
task_id_1,
task_id_2,

Check warning on line 458 in pueue/src/client/client.rs

View check run for this annotation

Codecov / codecov/patch

pueue/src/client/client.rs#L457-L458

Added lines #L457 - L458 were not covered by tests
}
.into(),
SubCommand::Enqueue {
Expand All @@ -462,10 +464,10 @@ impl Client {
all,
delay_until,
} => {
let selection = selection_from_params(*all, group, task_ids);
let selection = selection_from_params(all, &group, &task_ids);
EnqueueMessage {
tasks: selection,
enqueue_at: *delay_until,
enqueue_at: delay_until,
}
}
.into(),
Expand All @@ -475,7 +477,7 @@ impl Client {
all,
..
} => StartMessage {
tasks: selection_from_params(*all, group, task_ids),
tasks: selection_from_params(all, &group, &task_ids),

Check warning on line 480 in pueue/src/client/client.rs

View check run for this annotation

Codecov / codecov/patch

pueue/src/client/client.rs#L480

Added line #L480 was not covered by tests
}
.into(),
SubCommand::Pause {
Expand All @@ -485,8 +487,8 @@ impl Client {
all,
..
} => PauseMessage {
tasks: selection_from_params(*all, group, task_ids),
wait: *wait,
tasks: selection_from_params(all, &group, &task_ids),
wait,

Check warning on line 491 in pueue/src/client/client.rs

View check run for this annotation

Codecov / codecov/patch

pueue/src/client/client.rs#L490-L491

Added lines #L490 - L491 were not covered by tests
}
.into(),
SubCommand::Kill {
Expand All @@ -497,19 +499,32 @@ impl Client {
..
} => {
if self.settings.client.show_confirmation_questions {
self.handle_user_confirmation("kill", task_ids)?;
self.handle_user_confirmation("kill", &task_ids)?;

Check warning on line 502 in pueue/src/client/client.rs

View check run for this annotation

Codecov / codecov/patch

pueue/src/client/client.rs#L502

Added line #L502 was not covered by tests
}
KillMessage {
tasks: selection_from_params(*all, group, task_ids),
signal: signal.clone(),
tasks: selection_from_params(all, &group, &task_ids),
signal,

Check warning on line 506 in pueue/src/client/client.rs

View check run for this annotation

Codecov / codecov/patch

pueue/src/client/client.rs#L505-L506

Added lines #L505 - L506 were not covered by tests
}
.into()
}
SubCommand::Send { task_id, input } => SendMessage {
task_id: *task_id,
task_id,

Check warning on line 511 in pueue/src/client/client.rs

View check run for this annotation

Codecov / codecov/patch

pueue/src/client/client.rs#L511

Added line #L511 was not covered by tests
input: input.clone(),
}
.into(),
SubCommand::Env { cmd } => Message::from(match cmd {
EnvCommand::Set {
task_id,
key,
value,
} => EnvMessage::Set {
task_id,
key,
value,
},
EnvCommand::Unset { task_id, key } => EnvMessage::Unset { task_id, key },
}),

SubCommand::Group { cmd, .. } => match cmd {
Some(GroupCommand::Add { name, parallel }) => GroupMessage::Add {
name: name.to_owned(),
Expand All @@ -528,8 +543,8 @@ impl Client {
all,
..
} => {
let lines = determine_log_line_amount(*full, lines);
let selection = selection_from_params(*all, group, task_ids);
let lines = determine_log_line_amount(full, &lines);
let selection = selection_from_params(all, &group, &task_ids);

let message = LogRequestMessage {
tasks: selection,
Expand All @@ -538,17 +553,13 @@ impl Client {
};
Message::Log(message)
}
SubCommand::Follow { task_id, lines } => StreamRequestMessage {
task_id: *task_id,
lines: *lines,
}
.into(),
SubCommand::Follow { task_id, lines } => StreamRequestMessage { task_id, lines }.into(),
SubCommand::Clean {
successful_only,
group,
} => CleanMessage {
successful_only: *successful_only,
group: group.clone(),
successful_only,
group,

Check warning on line 562 in pueue/src/client/client.rs

View check run for this annotation

Codecov / codecov/patch

pueue/src/client/client.rs#L561-L562

Added lines #L561 - L562 were not covered by tests
}
.into(),
SubCommand::Reset { force, groups, .. } => {
Expand All @@ -570,9 +581,9 @@ impl Client {
group,
} => match parallel_tasks {
Some(parallel_tasks) => {
let group = group_or_default(group);
let group = group_or_default(&group);

Check warning on line 584 in pueue/src/client/client.rs

View check run for this annotation

Codecov / codecov/patch

pueue/src/client/client.rs#L584

Added line #L584 was not covered by tests
ParallelMessage {
parallel_tasks: *parallel_tasks,
parallel_tasks,

Check warning on line 586 in pueue/src/client/client.rs

View check run for this annotation

Codecov / codecov/patch

pueue/src/client/client.rs#L586

Added line #L586 was not covered by tests
group,
}
.into()
Expand Down
57 changes: 57 additions & 0 deletions pueue/src/daemon/network/message_handler/env.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
use pueue_lib::{network::message::*, settings::Settings, state::SharedState};

use crate::{
daemon::{network::message_handler::ok_or_failure_message, state_helper::save_state},
ok_or_save_state_failure,
};

/// Invoked on `pueue env`.
/// Manage environment variables for tasks.
/// - Set environment variables
/// - Unset environment variables
pub fn env(settings: &Settings, state: &SharedState, message: EnvMessage) -> Message {
let mut state = state.lock().unwrap();

let message = match message {
EnvMessage::Set {
task_id,
key,
value,
} => {
let Some(task) = state.tasks.get_mut(&task_id) else {
return create_failure_message(format!("No task with id {task_id}"));

Check warning on line 22 in pueue/src/daemon/network/message_handler/env.rs

View check run for this annotation

Codecov / codecov/patch

pueue/src/daemon/network/message_handler/env.rs#L22

Added line #L22 was not covered by tests
};

if !(task.is_queued() || task.is_stashed()) {
return create_failure_message("You can only edit stashed or queued tasks");

Check warning on line 26 in pueue/src/daemon/network/message_handler/env.rs

View check run for this annotation

Codecov / codecov/patch

pueue/src/daemon/network/message_handler/env.rs#L26

Added line #L26 was not covered by tests
}

task.envs.insert(key, value);

create_success_message("Environment variable set.")
}
EnvMessage::Unset { task_id, key } => {
let Some(task) = state.tasks.get_mut(&task_id) else {
return create_failure_message(format!("No task with id {task_id}"));

Check warning on line 35 in pueue/src/daemon/network/message_handler/env.rs

View check run for this annotation

Codecov / codecov/patch

pueue/src/daemon/network/message_handler/env.rs#L35

Added line #L35 was not covered by tests
};

if !(task.is_queued() || task.is_stashed()) {
return create_failure_message("You can only edit stashed or queued tasks");

Check warning on line 39 in pueue/src/daemon/network/message_handler/env.rs

View check run for this annotation

Codecov / codecov/patch

pueue/src/daemon/network/message_handler/env.rs#L39

Added line #L39 was not covered by tests
}

match task.envs.remove(&key) {
Some(_) => create_success_message("Environment variable unset."),
None => create_failure_message(format!(
"No environment variable with key '{key}' found."
)),

Check warning on line 46 in pueue/src/daemon/network/message_handler/env.rs

View check run for this annotation

Codecov / codecov/patch

pueue/src/daemon/network/message_handler/env.rs#L44-L46

Added lines #L44 - L46 were not covered by tests
}
}
};

// Save the state if there were any changes.
if let Message::Success(_) = message {
ok_or_save_state_failure!(save_state(&state, settings));
}

Check warning on line 54 in pueue/src/daemon/network/message_handler/env.rs

View check run for this annotation

Codecov / codecov/patch

pueue/src/daemon/network/message_handler/env.rs#L54

Added line #L54 was not covered by tests

message
}
22 changes: 14 additions & 8 deletions pueue/src/daemon/network/message_handler/group.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,21 @@
use std::collections::BTreeMap;

use pueue_lib::network::message::*;
use pueue_lib::settings::Settings;
use pueue_lib::state::{SharedState, PUEUE_DEFAULT_GROUP};
use pueue_lib::{failure_msg, success_msg};
use pueue_lib::{
failure_msg,
network::message::*,
settings::Settings,
state::{SharedState, PUEUE_DEFAULT_GROUP},
success_msg,
};

use crate::daemon::network::message_handler::ok_or_failure_message;
use crate::daemon::network::response_helper::ensure_group_exists;
use crate::daemon::process_handler::initiate_shutdown;
use crate::daemon::state_helper::save_state;
use crate::ok_or_save_state_failure;
use crate::{
daemon::{
network::response_helper::ensure_group_exists, process_handler::initiate_shutdown,
state_helper::save_state,
},
ok_or_save_state_failure,
};

/// Invoked on `pueue groups`.
/// Manage groups.
Expand Down
2 changes: 2 additions & 0 deletions pueue/src/daemon/network/message_handler/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ mod add;
mod clean;
mod edit;
mod enqueue;
mod env;
mod group;
mod kill;
mod log;
Expand All @@ -34,6 +35,7 @@ pub fn handle_message(message: Message, state: &SharedState, settings: &Settings
Message::Edit(editable_tasks) => edit::edit(settings, state, editable_tasks),
Message::EditRequest(task_ids) => edit::edit_request(state, task_ids),
Message::EditRestore(task_ids) => edit::edit_restore(state, task_ids),
Message::Env(message) => env::env(settings, state, message),
Message::Enqueue(message) => enqueue::enqueue(settings, state, message),
Message::Group(message) => group::group(settings, state, message),
Message::Kill(message) => kill::kill(settings, state, message),
Expand Down
1 change: 1 addition & 0 deletions pueue/src/daemon/process_handler/finish.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ pub fn handle_finished_tasks(settings: &Settings, state: &mut LockedState) {

task.clone()
};
info!("WTF");
spawn_callback(settings, state, &task);

if let TaskResult::Failed(_) = result {
Expand Down
Loading

0 comments on commit 161dc10

Please sign in to comment.