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

many: support refresh hold/unhold to API and CLI #12073

Merged
merged 9 commits into from Oct 25, 2022

Conversation

MiguelPires
Copy link
Contributor

@MiguelPires MiguelPires commented Aug 24, 2022

  • 40ee105 adds support for hold and unholding refreshes to the snapd REST API
  • bde4921 adds support for the snap refresh --hold/--unhold commands to the snap tool
  • 13ebf7d adds a spread test to integration test this feature

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.

thank you, did a pass. mostly small things and trying to clarify messages and help

client/snap_op.go Outdated Show resolved Hide resolved
client/snap_op.go Outdated Show resolved Hide resolved
tests/main/snap-refresh-hold/task.yaml Show resolved Hide resolved
tests/main/snap-refresh-hold/task.yaml Outdated Show resolved Hide resolved
daemon/api_snaps.go Outdated Show resolved Hide resolved
cmd/snap/cmd_snap_op.go Outdated Show resolved Hide resolved
daemon/api_snaps.go Outdated Show resolved Hide resolved
daemon/api_snaps.go Outdated Show resolved Hide resolved
daemon/api_snaps.go Outdated Show resolved Hide resolved
daemon/api_snaps.go Outdated Show resolved Hide resolved
@MiguelPires
Copy link
Contributor Author

@degville could you review the outputted text in this PR please? We'd like to make the help, output and error messages clear to users. They're in cmd/snap/cmd_snap_op.go and daemon/api_snaps.go

Copy link
Contributor

@degville degville left a comment

Choose a reason for hiding this comment

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

Thanks for pinging me! I've made a few comments, with the main suggestion being for the principle help text - but it's nothing major. It's difficult to find the path of least cognitive resistance with hold and held. Please feel free to ignore or update accordingly.

Comment on lines 98 to 101
Holds (--hold) specified for snaps are only applied to general refreshes ('snap
refresh' without specifying snaps and auto-refreshes), but snaps can still be
refreshed in specific refreshes (i.e, 'snap refresh snap-a snap-b'). Using
--hold without specifying any snaps will only hold auto-refreshes for all snaps.
Copy link
Contributor

Choose a reason for hiding this comment

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

I've tried tweaking this slightly to hopefully make our intentions clearer (I left the time specifics and syntax to the command options list):

Suggested change
Holds (--hold) specified for snaps are only applied to general refreshes ('snap
refresh' without specifying snaps and auto-refreshes), but snaps can still be
refreshed in specific refreshes (i.e, 'snap refresh snap-a snap-b'). Using
--hold without specifying any snaps will only hold auto-refreshes for all snaps.
Hold (--hold) is used to postpone general snap refresh updates for either all
snaps, or for the specified snaps. It is only effective with auto-refreshes and
refreshes that do not target snaps specifically. If a snap is first held but
then added to a refresh command, such as `snap refresh target-snap`, it will
still be refreshed.

Copy link
Collaborator

Choose a reason for hiding this comment

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

@degville I think in the reformulation is lost that "snap refresh --hold" blocks only auto-refreshes and not "snap refresh" (no specific snap) itself.

Copy link
Contributor

Choose a reason for hiding this comment

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

Thanks @pedronis, I'd forgotten that it didn't block a general snap refresh. Does this make it clearer?

Suggested change
Holds (--hold) specified for snaps are only applied to general refreshes ('snap
refresh' without specifying snaps and auto-refreshes), but snaps can still be
refreshed in specific refreshes (i.e, 'snap refresh snap-a snap-b'). Using
--hold without specifying any snaps will only hold auto-refreshes for all snaps.
Hold (--hold) is used to postpone automatic snap refresh updates for all snaps
when no snaps are specified, or for the specified snaps. It is only effective
with auto-refreshes and will not block either general refresh requests from
`snap refresh` or specific snap requests from `snap refresh target-snap`.

Copy link
Collaborator

@pedronis pedronis Sep 7, 2022

Choose a reason for hiding this comment

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

It does block general refreshes for specific snaps. So I still don't think I read that in the new version. Maybe the easiest is really to have two paragraphs, one about "snap refresh --hold" and a separate one about "snap refresh --hold <snap>"?

Copy link
Collaborator

Choose a reason for hiding this comment

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

I tried to split into a general/intro paragraph and then one paragraph about when no snaps are specified and one for snaps being specified.

cmd/snap/cmd_snap_op.go Outdated Show resolved Hide resolved
cmd/snap/cmd_snap_op.go Outdated Show resolved Hide resolved
cmd/snap/cmd_snap_op.go Outdated Show resolved Hide resolved
cmd/snap/cmd_snap_op.go Outdated Show resolved Hide resolved
@pedronis
Copy link
Collaborator

pedronis commented Sep 6, 2022

thanks @degville, I'll review your comments first and then @MiguelPires we'll see how to proceed

@pedronis pedronis self-requested a review September 6, 2022 12:05
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.

the summaries for the remove cases can probably be made to match more @degville suggestions for the cmd/snap ones

}

tss = []*state.TaskSet{ts}
msg = i18n.G("Remove hold on auto-refreshes of all snaps.")
Copy link
Collaborator

Choose a reason for hiding this comment

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

this probably can be changed to be a bit more like the new cmd/snap message

return nil, err
}

msg = fmt.Sprintf(i18n.G("Remove hold on general refreshes of %s."), strutil.Quoted(inst.Snaps))
Copy link
Collaborator

Choose a reason for hiding this comment

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

same

@pedronis
Copy link
Collaborator

pedronis commented Sep 7, 2022

marking blocked as while the command behavior matches our knoewn use cases and precedent, we likely want first to make the API itself less implicit/ambiguous

I talked about this with @MiguelPires

@pedronis
Copy link
Collaborator

I rebased this on master and switched it to use the new API. Next step is adding a level parameter to the hold APIs themselves

MiguelPires and others added 8 commits October 17, 2022 21:55
Signed-off-by: Miguel Pires <miguel.pires@canonical.com>
Signed-off-by: Miguel Pires <miguel.pires@canonical.com>
Signed-off-by: Miguel Pires <miguel.pires@canonical.com>
Signed-off-by: Miguel Pires <miguel.pires@canonical.com>
Signed-off-by: Miguel Pires <miguel.pires@canonical.com>
it can have values "auto-refresh" or "general" matching
snapstate.HoldAutoRefresh or snapstate.HoldGeneral

holding general refreshes for all snaps is not supported atm
Comment on lines +105 to +108
When specific snaps are mentioned --hold is effective on their auto-refreshes
and will also silently block general refresh requests from 'snap refresh' of
those snaps while explicit targeted 'snap refresh target-snap' will not be
blocked.
Copy link
Contributor

Choose a reason for hiding this comment

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

@pedronis Thanks for thinking about this - I much prefer your split approach, which I think is far easier to understand. It all looks good but I've tried to clarify the final paragraph slightly by copying the terminology and structure of the previous paragraph.

Suggested change
When specific snaps are mentioned --hold is effective on their auto-refreshes
and will also silently block general refresh requests from 'snap refresh' of
those snaps while explicit targeted 'snap refresh target-snap' will not be
blocked.
When snaps are specified --hold is effective on both their auto-refreshes
and general refresh requests from `snap refresh`. However, specific snap
requests from 'snap refresh target-snap' remain unblocked and will proceed.

Copy link
Contributor Author

@MiguelPires MiguelPires left a comment

Choose a reason for hiding this comment

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

The recent changes LGTM

@pedronis pedronis added this to the 2.58 milestone Oct 20, 2022
Copy link
Contributor

@mvo5 mvo5 left a comment

Choose a reason for hiding this comment

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

Thanks, this is fine and my nitpicks can be follwups

changeID, err = x.client.HoldRefreshesMany(names, &opts)
}

if err != nil {
Copy link
Contributor

Choose a reason for hiding this comment

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

(super)nitpick. I would remove the newline so that the err check is as close as possible to the branches that generate the errors.

names := installedSnapNames(x.Positional.Snaps)
var changeID string
opts.HoldLevel = "general"
if len(names) == 0 {
Copy link
Contributor

Choose a reason for hiding this comment

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

(nitpick^3) I wonder if this would looks nicer as a switch ?

if inst.Time == "" {
return errors.New("hold action requires a non-empty time value")
} else if inst.Time != "forever" {
_, err := time.Parse(time.RFC3339, inst.Time)
Copy link
Contributor

Choose a reason for hiding this comment

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

(nitpick) this could be a sinfle line: if _, err := time...; err != nil {

@mvo5
Copy link
Contributor

mvo5 commented Oct 24, 2022

Looking at the spread tests I see one issue that looks related to this PR:

2022-10-17T20:56:21.7279655Z 2022-10-17 20:56:21 Executing google:ubuntu-18.04-64:tests/main/parallel-install-basic (oct172016-343438) (312/606)...
2022-10-17T20:56:22.9477219Z ##[error]2022-10-17 20:56:22 Error executing google:ubuntu-18.04-64:tests/main/snap-refresh-hold (oct172016-343420) : 
2022-10-17T20:56:22.9485780Z -----
2022-10-17T20:56:22.9486494Z + echo 'No snaps auto-refresh in an all-snaps hold'
2022-10-17T20:56:22.9487098Z No snaps auto-refresh in an all-snaps hold
2022-10-17T20:56:22.9487641Z + snap refresh --hold=forever
2022-10-17T20:56:22.9488168Z Auto-refresh of all snaps held until forever
2022-10-17T20:56:22.9488573Z + systemctl stop snapd.service snapd.socket
2022-10-17T20:56:22.9489300Z + /home/gopath/src/github.com/snapcore/snapd/tests/lib/tools/snapd-state change-snap-channel test-snapd-tools edge
2022-10-17T20:56:22.9490111Z + /home/gopath/src/github.com/snapcore/snapd/tests/lib/tools/snapd-state force-autorefresh
2022-10-17T20:56:22.9490639Z + systemctl start snapd.socket snapd.service
2022-10-17T20:56:22.9491263Z + retry -n 5 --quiet sh -c 'snap changes | tail -2 | grep "Done.*Auto-refresh"'
2022-10-17T20:56:22.9496048Z + echo 'Snap doesn'\''t auto-refresh with a specific hold'
2022-10-17T20:56:22.9496665Z Snap doesn't auto-refresh with a specific hold
2022-10-17T20:56:22.9497002Z + reset
2022-10-17T20:56:22.9497761Z + snap refresh --channel=latest/stable test-snapd-tools
2022-10-17T20:56:22.9498516Z test-snapd-tools 1.0 from Test snaps (test-snaps-canonical) refreshed
2022-10-17T20:56:22.9499103Z + snap refresh --channel=latest/stable test-snapd-tools_instance
2022-10-17T20:56:22.9499670Z snap "test-snapd-tools_instance" has no updates available
2022-10-17T20:56:22.9500205Z + snap refresh --unhold test-snapd-tools
2022-10-17T20:56:22.9501225Z Removed general refresh hold of "test-snapd-tools"
2022-10-17T20:56:22.9501679Z + snap refresh --unhold
2022-10-17T20:56:22.9502996Z Removed auto-refresh hold on all snaps
2022-10-17T20:56:22.9503590Z + snap refresh --hold test-snapd-tools
2022-10-17T20:56:22.9590270Z General refreshes of "test-snapd-tools" held until forever
2022-10-17T20:56:22.9590841Z + systemctl stop snapd.service snapd.socket
2022-10-17T20:56:22.9591627Z + /home/gopath/src/github.com/snapcore/snapd/tests/lib/tools/snapd-state change-snap-channel test-snapd-tools edge
2022-10-17T20:56:22.9592450Z + /home/gopath/src/github.com/snapcore/snapd/tests/lib/tools/snapd-state change-snap-channel test-snapd-tools_instance edge
2022-10-17T20:56:22.9593273Z + /home/gopath/src/github.com/snapcore/snapd/tests/lib/tools/snapd-state force-autorefresh
2022-10-17T20:56:22.9593806Z + systemctl start snapd.socket snapd.service
2022-10-17T20:56:22.9594569Z + retry -n 5 --quiet sh -c 'snap changes | tail -2 | grep "Done.*Auto-refresh snap "test-snapd-tools_instance""'
2022-10-17T20:56:22.9595138Z + echo 'Snaps auto-refresh without holds'
2022-10-17T20:56:22.9595616Z Snaps auto-refresh without holds
2022-10-17T20:56:22.9595956Z + reset
2022-10-17T20:56:22.9596364Z + snap refresh --channel=latest/stable test-snapd-tools
2022-10-17T20:56:22.9614942Z test-snapd-tools 1.0 from Test snaps (test-snaps-canonical) refreshed
2022-10-17T20:56:22.9615885Z + snap refresh --channel=latest/stable test-snapd-tools_instance
2022-10-17T20:56:22.9616485Z error: snap "test-snapd-tools_instance" has "auto-refresh" change in progress
2022-10-17T20:56:22.9616919Z -----

@pedronis
Copy link
Collaborator

2022-10-17T20:56:22.9596364Z + snap refresh --channel=latest/stable test-snapd-tools
2022-10-17T20:56:22.9614942Z test-snapd-tools 1.0 from Test snaps (test-snaps-canonical) refreshed
2022-10-17T20:56:22.9615885Z + snap refresh --channel=latest/stable test-snapd-tools_instance
2022-10-17T20:56:22.9616485Z error: snap "test-snapd-tools_instance" has "auto-refresh" change in progress

it seems the auto-refresh for which we check above is still in progress, is the grep check wrong? or do we have a very unexpected race?

A missing ! was preventing the test from failing if the auto-refresh
for test-snapd-tools_instance wasn't completed by the end of retry.
This commit also adds another check to ensure that the other snap isn't
auto-refreshed. Since this bug was discovered because the
auto-refresh was still ongoing after the retry, it's possible that even
with the fix more retries are necessary so I doubled the number.

Signed-off-by: Miguel Pires <miguel.pires@canonical.com>
Copy link
Contributor

@mvo5 mvo5 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!

@mvo5 mvo5 merged commit f73eb23 into snapcore:master Oct 25, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
4 participants