Skip to content

Add plugins support#4

Draft
damdo wants to merge 1 commit intomainfrom
add-plugins-support
Draft

Add plugins support#4
damdo wants to merge 1 commit intomainfrom
add-plugins-support

Conversation

@damdo
Copy link
Collaborator

@damdo damdo commented Sep 7, 2023

As part of the update system efforts, we are introducing the ability to specify plugins that allow to push and pull updates from many different sources (e.g. OCI, S3, ...) in addition to the natively supported HTTP file server source.

As such in gokrazy/gokrazy#173 we want to give selfupdate the ability to understand payload links that differ from HTTP and may be coming from a GUS update response.

To be able to do this, selfupdate must give the user the ability to specify a plugin name (which will be used by selfupdate to reference the plugin binary) and some credentials that the plugin will use to fetch the update from the source registries (think for example at the credentials necessary to fetch an OCI update payload from an OCI registry or at the AWS credentials necessary to pull a file from AWS S3).

This PR aims at implementing this ability for selfupdate.

Note:
With this approach selfupdate will be able to load only one plugin at a time in addition to the already natively supported HTTP fetching mechanism.

selfupdate.go Outdated
Comment on lines 108 to 112
log.Print("requesting reboot")
// TODO: change call from target.Reboot to something like target.ScheduleReboot
// which can asyncronouly perform the task instead of waiting
// for all the services to shutdown and then ack the reboot,
// othewise this causes a deadlock as the selfupdate service won't SIGTERM cleanly
// until the reboot ack is received, but won't receive the ack until all services shut down,
// causing a delayed reboot until SIGKILL kicks in.
if err := target.Reboot(); err != nil {
return fmt.Errorf("reboot: %v", err)
}
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This one will need some thought

Copy link
Contributor

Choose a reason for hiding this comment

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

Hmm, why will selfupdate not SIGTERM cleanly in this state? I would have expected it to. SIGINT and SIGTERM are hooked up to context cancellation in selfupdate’s main function.

Copy link
Collaborator Author

@damdo damdo May 25, 2025

Choose a reason for hiding this comment

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

The problem here is that the Reboot() is blocking:

As such I can think of two options here:

  1. either we make selfupdate exit cleanly on SIGTERM by adding a ctx to cancel the target.Reboot() call
  2. or we add a target.AsyncReboot(), to call in this selfupdate case, that passes an async=true arg to the /reboot HTTP call, which acks the /reboot HTTP API call as 200 and runs the killSupervisedServicesAndUmountPerm async in a separate goroutine, which should avoid the waiting

WDYT?

Copy link
Contributor

Choose a reason for hiding this comment

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

I think handling target.Reboot getting interrupted by SIGTERM is the better option here, as it seems simpler and does not require increasing the API surface.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Ok cool, created a PR for that here: gokrazy/updater#2

Copy link
Contributor

Choose a reason for hiding this comment

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

Actually, I just noticed that there is another case where the blocking behavior of /reboot gets in the way: when updating gokrazy via Caddy (e.g. for using Tailscale for authentication, see gokrazy/gokrazy#257), we’ll also encounter an error, and a timeout.

Maybe we should give the asynchronous reboot a try. Do we need another parameter for that or could we just change how reboot works? Did you experiment with that?

(We can still introduce a context to gokrazy/updater independently.)

Copy link
Collaborator Author

@damdo damdo Jun 2, 2025

Choose a reason for hiding this comment

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

main.go Outdated
ticker := time.NewTicker(frequency)

for {
for c := time.Tick(frequency); ; {
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Changing this so then we get an immediate first check without waiting an extra frequency interval.

Also changing the skipWaiting to only skip the Jitter once, the first time.

These two changes combined still achieve the same initially defined behaviour for skipWaiting, but improve the first check also in cases where skipWaiting is set to false

damdo added a commit to damdo/updater that referenced this pull request May 29, 2025
to be able to cancel it from the caller side.
Ref: gokrazy/selfupdate#4 (comment)
damdo added a commit to damdo/updater that referenced this pull request May 31, 2025
to be able to cancel it from the caller side.
Ref: gokrazy/selfupdate#4 (comment)
stapelberg pushed a commit to gokrazy/updater that referenced this pull request Jun 1, 2025
…to be able to cancel operations from the caller side.

Ref: gokrazy/selfupdate#4 (comment)
damdo added a commit that referenced this pull request Jun 2, 2025
this updates to the latest gokrazy/updater to leverage the context
change to allow cancelling the target.Reboot() call and finish
performing the update cleanly.
Context: #4 (comment)
@damdo damdo force-pushed the add-plugins-support branch from 82b56da to 0254e5b Compare June 2, 2025 15:06
@damdo damdo force-pushed the add-plugins-support branch from 0254e5b to e096dd0 Compare June 2, 2025 15:08
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.

2 participants