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

store: add functions to download snap icons #14990

Open
wants to merge 13 commits into
base: master
Choose a base branch
from

Conversation

olivercalder
Copy link
Member

These new functions, downloadIconImpl and DownloadIcon, mirror their non-icon counterparts downloadImpl and Download, except that because snap icons are small, simple assets on a fileserver, there is no need for snap-specific headers, authentication, partial downloads, or caching.

These will be used in the future in order to download a snap's icon whenever the new .snap blob is downloaded for that snap and linked to a snap icons directory so that the snapd API can serve snap icons from local icon files, rather than returning an error if the snap does not ship an icon at meta/gui/icon.*.

This work is tracked internally by https://warthogs.atlassian.net/browse/SNAPDENG-34095

These new functions, `downloadIconImpl` and `DownloadIcon`, mirror their
non-icon counterparts `downloadImpl` and `Download`, except that because
snap icons are small, simple assets on a fileserver, there is no need
for snap-specific headers, authentication, partial downloads, or
caching.

These will be used in the future in order to download a snap's icon
whenever the new `.snap` blob is downloaded for that snap and linked to
a snap icons directory so that the snapd API can serve snap icons from
local icon files, rather than returning an error if the snap does not
ship an icon at `meta/gui/icon.*`.

Signed-off-by: Oliver Calder <[email protected]>
@olivercalder olivercalder added the Needs Samuele review Needs a review from Samuele before it can land label Jan 28, 2025
Copy link

codecov bot commented Jan 28, 2025

Codecov Report

Attention: Patch coverage is 69.41176% with 26 lines in your changes missing coverage. Please review.

Please upload report for BASE (master@103b4eb). Learn more about missing BASE report.
Report is 69 commits behind head on master.

Files with missing lines Patch % Lines
store/store_download.go 68.91% 18 Missing and 5 partials ⚠️
store/store.go 72.72% 2 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff            @@
##             master   #14990   +/-   ##
=========================================
  Coverage          ?   78.21%           
=========================================
  Files             ?     1164           
  Lines             ?   154433           
  Branches          ?        0           
=========================================
  Hits              ?   120791           
  Misses            ?    26194           
  Partials          ?     7448           
Flag Coverage Δ
unittests 78.21% <69.41%> (?)

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.

Copy link

github-actions bot commented Jan 28, 2025

Wed Feb 5 01:05:14 UTC 2025
The following results are from: https://github.com/canonical/snapd/actions/runs/13146270163

Failures:

Executing:

  • google-distro-1:debian-11-64:tests/main/auto-refresh-gating
  • openstack:fedora-41-64:tests/main/auto-refresh-gating
  • google:ubuntu-20.04-64:tests/main/lxd:snapd_cgroup_just_inside
  • google:ubuntu-20.04-64:tests/main/snapd-state
  • google:ubuntu-20.04-64:tests/main/auto-refresh-gating
  • google:ubuntu-24.10-64:tests/main/auto-refresh-gating
  • google:ubuntu-24.04-64:tests/main/snapd-state

Restoring:

  • google-core:ubuntu-core-18-64:tests/core/kernel-base-gadget-single-reboot-failover
  • google-core:ubuntu-core-18-64:tests/core/auto-refresh-backoff-after-reboot:kernel

@olivercalder olivercalder requested a review from pedronis January 28, 2025 04:12
Copy link
Contributor

@ZeyadYasser ZeyadYasser left a comment

Choose a reason for hiding this comment

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

Looks good, small nitpicks and a question.

Is the icon file validation (max size, format ..etc) intentionally ignored because snapd is guaranteed to get the URL from the store which should be trusted?

store/store.go Outdated Show resolved Hide resolved
store/store.go Outdated Show resolved Hide resolved
Copy link
Member

@andrewphelpsj andrewphelpsj left a comment

Choose a reason for hiding this comment

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

Some questions about the cleanup code, and maybe consider making that retry loop body into a function?

store/store.go Outdated Show resolved Hide resolved
store/store_download.go Outdated Show resolved Hide resolved
var finalErr error
startTime := time.Now()
for attempt := retry.Start(downloadRetryStrategy, nil); attempt.Next(); {
httputil.MaybeLogRetryAttempt(iconURL.String(), attempt, startTime)
Copy link
Member

Choose a reason for hiding this comment

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

Would it be possible to make this inner loop a function? I understand it might be awkward because you need to hold on to finalErr.

Copy link
Member Author

Choose a reason for hiding this comment

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

I've made it a function now

// ... and ensure that the tempfile is removed
c.Assert(osutil.FileExists(tmpfile.Name()), Equals, false)
// ... because it's been renamed to the target path already
c.Assert(osutil.FileExists(path), Equals, true)
Copy link
Member

Choose a reason for hiding this comment

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

It seems this test is expecting that behavior from my other comment? Seems like this could be avoided? If we fail to download the file and attempt cleanup, I feel like we should properly do the cleanup, unless there is some other use case I'm missing.

Copy link
Member Author

Choose a reason for hiding this comment

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

My guess is that if the file is renamed, its contents are good, so for large .snap files we want to keep it around. But that doesn't hold up since an error would suggest it's not in the cache, so it wouldn't be used on subsequent download anyway. So I'm not really sure why. Some git spelunking shows the code this is originally based on was written by John Lenton to support preserving partial download files after error: ebbb57e

I really don't know why the sync occurs after the rename. On unix, the rename should be atomic. Maybe it's an optimization to avoid committing the write to disk until we're sure the rename will work? But that seems silly, since a sync may occur anyway in the background during this time. Either way, it seems like an optimization for dealing with large .snap files, not applicable here.

Copy link
Member Author

Choose a reason for hiding this comment

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

All of this was now replaced with usage of osutil.AtomicFile

ZeyadYasser
ZeyadYasser previously approved these changes Jan 30, 2025
Copy link
Contributor

@ZeyadYasser ZeyadYasser left a comment

Choose a reason for hiding this comment

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

Thank you!

Other than addressing comments from @andrewphelpsj, I think this looks good.

Copy link
Collaborator

@pedronis pedronis left a comment

Choose a reason for hiding this comment

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

remark about being careful with the download length/icon size

store/store_download.go Outdated Show resolved Hide resolved
@pedronis pedronis requested a review from bboozzoo January 30, 2025 17:22
@pedronis
Copy link
Collaborator

@olivercalder I added @bboozzoo to also look at this

Copy link
Collaborator

@pedronis pedronis left a comment

Choose a reason for hiding this comment

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

actual vote

Copy link
Collaborator

@pedronis pedronis left a comment

Choose a reason for hiding this comment

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

further comment

store/store_download.go Outdated Show resolved Hide resolved
@pedronis pedronis dismissed ZeyadYasser’s stale review February 3, 2025 13:07

this will need a re-review

store/store_download.go Outdated Show resolved Hide resolved
store/store_download.go Outdated Show resolved Hide resolved
store/store_download.go Outdated Show resolved Hide resolved
store/store_download.go Outdated Show resolved Hide resolved
store/store_download.go Outdated Show resolved Hide resolved
store/store_download.go Outdated Show resolved Hide resolved
store/store_download.go Outdated Show resolved Hide resolved
store/store_download.go Outdated Show resolved Hide resolved
logger.Debugf("Download size for %s: %d", downloadURL, resp.ContentLength)
}

_, finalErr = io.CopyN(w, resp.Body, resp.ContentLength)
Copy link
Contributor

Choose a reason for hiding this comment

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

btw. no integrity check?

Copy link
Contributor

@bboozzoo bboozzoo Feb 4, 2025

Choose a reason for hiding this comment

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

I think we need a test to verify the size limit

Copy link
Member Author

Choose a reason for hiding this comment

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

We don't have any information about what the icon contents are supposed to be, so there's no way to check them. We could leverage the etag to see if the server reports that the file has changed, but I don't think there's a way to use the etag to check for file integrity.

I'll add a test to verify the size limit though, thanks.

olivercalder and others added 2 commits February 4, 2025 11:53
Copy link
Member

@andrewphelpsj andrewphelpsj left a comment

Choose a reason for hiding this comment

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

Thanks, some small comments.

store/store_download_test.go Outdated Show resolved Hide resolved
store/store_download.go Outdated Show resolved Hide resolved
store/store_download.go Outdated Show resolved Hide resolved
store/store_download.go Outdated Show resolved Hide resolved
Also add comments noting that the http clients for both snap downloads
and snap icon downloads have no timeout defined.

Signed-off-by: Oliver Calder <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Needs Samuele review Needs a review from Samuele before it can land
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants