Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add(task): Allow editing environment variables #584

Merged
merged 1 commit into from
Dec 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 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 @@
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 @@
},
}

#[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::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 @@
/// 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
..
} => {
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 @@
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 @@
};
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 @@
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
Loading