Skip to content

many: attempt to clean up potentially corrupted files during download undo#16691

Open
alfonsosanchezbeato wants to merge 6 commits intocanonical:masterfrom
alfonsosanchezbeato:bboozzoo_downloads-undo-cleanup
Open

many: attempt to clean up potentially corrupted files during download undo#16691
alfonsosanchezbeato wants to merge 6 commits intocanonical:masterfrom
alfonsosanchezbeato:bboozzoo_downloads-undo-cleanup

Conversation

@alfonsosanchezbeato
Copy link
Member

Add proper undo to snap downloads step. Attempt to guess whether the
downloaded file could be corrupted and if it is, try to clean it up.

Related: SNAPDENG-36484

This is #16650 plus some test fixes. cc @bboozzoo .

Signed-off-by: Maciej Borzecki <maciej.borzecki@canonical.com>
…oad undo

Add proper undo to snap downloads step. Attempt to guess whether the
downloaded file could be corrupted and if it is, try to clean it up.

Related: SNAPDENG-36484

Signed-off-by: Maciej Borzecki <maciej.borzecki@canonical.com>
Signed-off-by: Maciej Borzecki <maciej.borzecki@canonical.com>
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds an explicit undo handler for the download-snap task so that, when a download step is undone, snapd attempts to remove the downloaded snap file and (when possible) drop a potentially corrupted corresponding entry from the downloads cache.

Changes:

  • Introduce StoreService.CleanupDownloadArtifacts() and implement it in the store layer (including cache Open/Drop support) to remove the download target and optionally remove a corrupted cache entry.
  • Wire a new undoDownloadSnap handler for the download-snap task in snapstate, calling the store cleanup method without failing the overall undo flow.
  • Add unit and spread tests to validate cleanup behavior for corrupted downloads and updated undo operation sequencing.

Reviewed changes

Copilot reviewed 13 out of 13 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
tests/main/snap-download-corrupted-cleanup/task.yaml New spread test to validate that a corrupted snap blob and its cache entry are removed during undo of download-snap.
store/storetest/storetest.go Updates the panicking test Store stub to satisfy the expanded StoreService interface.
store/store_download_test.go Extends cache test doubles with Open/Drop and adds coverage for CleanupDownloadArtifacts.
store/store_download.go Implements CleanupDownloadArtifacts in the store, including cache corruption detection and best-effort cleanup.
store/cache_test.go Adds coverage for dropping cache entries and verifying hardlink count changes.
store/cache.go Extends download cache interface and CacheManager with Drop and Open operations.
overlord/snapstate/snapstate_update_test.go Adjusts expected fake ops and test download info to include sha3 where needed for cleanup.
overlord/snapstate/snapstate_install_test.go Updates expected undo op sequences to include store cleanup of download artifacts.
overlord/snapstate/snapmgr.go Switches download-snap undo handler from undoPrepareSnap to the new undoDownloadSnap.
overlord/snapstate/handlers_download_test.go Adds unit tests ensuring undoDownloadSnap calls cleanup and treats cleanup failures as non-fatal.
overlord/snapstate/handlers.go Adds undoDownloadSnap implementation calling StoreService.CleanupDownloadArtifacts.
overlord/snapstate/backend_test.go Extends fake store/backend op tracking to include sha3 for cleanup calls.
overlord/snapstate/backend.go Extends StoreService interface with CleanupDownloadArtifacts.

return s.cacher.Cleanup()
}

// CleanupDownloadsCacheEntry attempts to clean up download artifacts associated
Copy link

Copilot AI Feb 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The doc comment refers to CleanupDownloadsCacheEntry, but the function is named CleanupDownloadArtifacts. Please update the comment to match so it’s discoverable via godoc and grep.

Suggested change
// CleanupDownloadsCacheEntry attempts to clean up download artifacts associated
// CleanupDownloadArtifacts attempts to clean up download artifacts associated

Copilot uses AI. Check for mistakes.
var err error
// TODO:GOVERSION: use errors.Join
if rerr := os.Remove(targetFn); rerr != nil && !errors.Is(rerr, fs.ErrNotExist) {
err = strutil.JoinErrors(err, fmt.Errorf("cannot remove corrupted file: %w", rerr))
Copy link

Copilot AI Feb 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This error message says "corrupted file", but this function unconditionally removes the download target during undo even when it may be a valid snap. Consider using a more accurate message (e.g. "downloaded file") to avoid misleading logs/error chains.

Suggested change
err = strutil.JoinErrors(err, fmt.Errorf("cannot remove corrupted file: %w", rerr))
err = strutil.JoinErrors(err, fmt.Errorf("cannot remove downloaded file: %w", rerr))

Copilot uses AI. Check for mistakes.
}

func (Store) CleanupDownloadArtifacts(targetFn string, dl *snap.DownloadInfo) error {
panic("CleaupnDownloadArtifacts not expected")
Copy link

Copilot AI Feb 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo in panic message: "CleaupnDownloadArtifacts" should be "CleanupDownloadArtifacts".

Suggested change
panic("CleaupnDownloadArtifacts not expected")
panic("CleanupDownloadArtifacts not expected")

Copilot uses AI. Check for mistakes.
if co.inCache[cacheKey] {
s := "content"

// strings.NewReader returns an *io.Reader that also implements Seeker
Copy link

Copilot AI Feb 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment is incorrect: strings.NewReader returns a *strings.Reader (which implements io.Reader and io.Seeker), not an "*io.Reader".

Suggested change
// strings.NewReader returns an *io.Reader that also implements Seeker
// strings.NewReader returns a *strings.Reader, which implements io.Reader and io.Seeker

Copilot uses AI. Check for mistakes.
s.testUndoDownloadSnapFile(c, cleanupOk)
}

func (s *downloadSnapSuite) TestUndoDownloadSnapFileRemovedNotFatal(c *C) {
Copy link

Copilot AI Feb 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test name suggests file removal is being exercised, but the scenario only injects a CleanupDownloadArtifacts error and asserts it’s non-fatal. Consider renaming to reflect the actual behavior under test (e.g. cleanup error is not fatal).

Suggested change
func (s *downloadSnapSuite) TestUndoDownloadSnapFileRemovedNotFatal(c *C) {
func (s *downloadSnapSuite) TestUndoDownloadSnapCleanupErrorNotFatal(c *C) {

Copilot uses AI. Check for mistakes.

h := crypto.SHA3_384.New()
if _, cerr := io.Copy(h, f); cerr != nil {
return err
Copy link

Copilot AI Feb 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the io.Copy error path, this returns the outer err variable (which may be nil) instead of returning/propagating cerr. This would silently ignore read/checksum failures and potentially skip dropping a corrupted cache entry.

Suggested change
return err
return fmt.Errorf("cannot checksum cached entry: %w", cerr)

Copilot uses AI. Check for mistakes.
@github-actions
Copy link

github-actions bot commented Feb 27, 2026

Sat Feb 28 05:19:20 UTC 2026
The following results are from: https://github.com/canonical/snapd/actions/runs/22505929840

Failures:

Executing:

  • openstack:arch-linux-64:tests/main/snap-quota-memory
  • openstack:arch-linux-64:tests/main/snap-download-corrupted-cleanup
  • openstack:debian-12-64:tests/main/snap-download-corrupted-cleanup
  • openstack:ubuntu-core-18-64:tests/main/snap-download-corrupted-cleanup
  • openstack:ubuntu-core-20-64:tests/main/snap-download-corrupted-cleanup
  • openstack:ubuntu-core-24-64:tests/main/snap-download-corrupted-cleanup
  • openstack:ubuntu-20.04-64:tests/main/bad-meta-file-types
  • openstack:ubuntu-20.04-64:tests/main/snap-download-corrupted-cleanup
  • openstack:ubuntu-25.10-64:tests/main/snap-download-corrupted-cleanup
  • openstack:ubuntu-24.04-64:tests/main/snap-download-corrupted-cleanup

Restoring:

  • openstack:ubuntu-25.10-64:tests/main/apparmor-prompting-snapd-startup
  • openstack:ubuntu-25.10-64:tests/main/
  • openstack:ubuntu-25.10-64:

Skipped tests from snapd-testing-skip

  • openstack:ubuntu-24.04-64:tests/main/i18n

@alfonsosanchezbeato alfonsosanchezbeato force-pushed the bboozzoo_downloads-undo-cleanup branch from 5292f0a to 9374699 Compare February 27, 2026 22:15
@codecov
Copy link

codecov bot commented Feb 27, 2026

Codecov Report

❌ Patch coverage is 55.05618% with 40 lines in your changes missing coverage. Please review.
✅ Project coverage is 77.52%. Comparing base (0f390a0) to head (9374699).

Files with missing lines Patch % Lines
store/cache.go 41.93% 16 Missing and 2 partials ⚠️
store/store_download.go 51.51% 11 Missing and 5 partials ⚠️
overlord/snapstate/handlers.go 81.81% 3 Missing and 1 partial ⚠️
store/storetest/storetest.go 0.00% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master   #16691      +/-   ##
==========================================
- Coverage   77.54%   77.52%   -0.02%     
==========================================
  Files        1360     1357       -3     
  Lines      187256   187328      +72     
  Branches     2446     2446              
==========================================
+ Hits       145200   145230      +30     
- Misses      33278    33309      +31     
- Partials     8778     8789      +11     
Flag Coverage Δ
unittests 77.52% <55.05%> (-0.02%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants