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

[wicket] before starting a new update, require that update state be cleared #4452

Merged
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
21 changes: 10 additions & 11 deletions wicketd/src/update_tracker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -227,24 +227,23 @@ impl UpdateTracker {

let mut errors = Vec::new();

// Check that we're not already updating any of these SPs.
let update_in_progress: Vec<_> = sps
// Check that we don't already have any update state for these SPs.
let existing_updates: Vec<_> = sps
.iter()
.filter(|sp| {
// If we don't have any update data for this SP, it's not in
// progress.
//
// If we do, it's in progress if the task is not finished.
update_data
.sp_update_data
.get(sp)
.map_or(false, |data| !data.task.is_finished())
// This used to check that the task was finished, but we changed
// that in favor of forcing users to clear update state before
// starting a new one.
update_data.sp_update_data.get(sp).is_some()
})
.copied()
.collect();

if !update_in_progress.is_empty() {
errors.push(StartUpdateError::UpdateInProgress(update_in_progress));
if !existing_updates.is_empty() {
errors.push(StartUpdateError::ExistingUpdates(existing_updates));
}

let plan = update_data.artifact_store.current_plan();
Expand Down Expand Up @@ -709,8 +708,8 @@ impl UpdateTrackerData {
pub enum StartUpdateError {
#[error("no TUF repository available")]
TufRepositoryUnavailable,
#[error("targets are already being updated: {}", sps_to_string(.0))]
UpdateInProgress(Vec<SpIdentifier>),
#[error("existing update data found (must clear state before starting): {}", sps_to_string(.0))]
ExistingUpdates(Vec<SpIdentifier>),
}

#[derive(Debug, Clone, Error, Eq, PartialEq)]
Expand Down
26 changes: 23 additions & 3 deletions wicketd/tests/integration_tests/updates.rs
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,26 @@ async fn test_updates() {
}
}

// Try starting the update again -- this should fail because we require that update state is
// cleared before starting a new one.
{
let error = wicketd_testctx
.wicketd_client
.post_start_update(&params)
.await
.expect_err(
"post_start_update should fail \
since update data is already present",
);
let error_str = error.to_string();
assert!(
// Errors lose type information across the OpenAPI boundary, so sadly we have to match on
// the error string.
error_str.contains("existing update data found"),
"unexpected error: {error_str}"
);
}

// Try clearing the update via the wicket CLI.
{
let args = vec![
Expand Down Expand Up @@ -426,8 +446,8 @@ async fn test_update_races() {
.await
.expect_err("failed because update is currently running");

// Also try starting another fake update, which should fail -- we don't let
// updates be started in the middle of other updates.
// Also try starting another fake update, which should fail -- we don't let updates be started
// if there's current update state.
{
let (_, receiver) = watch::channel(());
let err = wicketd_testctx
Expand All @@ -439,7 +459,7 @@ async fn test_update_races() {
assert_eq!(err.len(), 1, "one error returned: {err:?}");
assert_eq!(
err.first().unwrap(),
&StartUpdateError::UpdateInProgress(vec![sp])
&StartUpdateError::ExistingUpdates(vec![sp])
);
}

Expand Down