Skip to content

Commit

Permalink
Disable grab download resume
Browse files Browse the repository at this point in the history
This is to mitigate cases like #4296

By default grab tries to resume the download if the file name determined from either the url or from content-type headers already exists. This makes things go side ways, if the existing file is smaller than the new one, the old content would still be there and only the "extra" new bytes would get written. I.e. the download would be "resumed". 🤦

So this change disables resuming altogether fro grab.

To be able to download and replace k0s without resuming, i.e. "truncate" the file in-between. We need to force the download to download it as k0s.tmp first. Only after that we can safely move the file as truncating a running binary is not allowed and will error with `text file busy`.

This is a minimal possible fix that we can easily backport. @twz123 is already working on bigger refactoring of autopilot download functionality that gets rid of grab. Grab seems to bring more (bad) surprises than real benefits. In the end, we just download files and we should pretty much always just replace them. No need for full library dependecy for that.

Signed-off-by: Jussi Nummelin <[email protected]>
  • Loading branch information
jnummelin committed Sep 26, 2024
1 parent 65647e9 commit 76b87d4
Show file tree
Hide file tree
Showing 5 changed files with 19 additions and 13 deletions.
1 change: 1 addition & 0 deletions pkg/autopilot/constant/static.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ const (
AutopilotNamespace = "k0s-autopilot"
AutopilotConfigName = AutopilotName
K0sBinaryDir = "/usr/local/bin"
K0sTempFilename = "k0s.tmp"
K0sDefaultDataDir = "/var/lib/k0s"
K0sManifestSubDir = "manifests"
K0sImagesDir = "images"
Expand Down
1 change: 0 additions & 1 deletion pkg/autopilot/controller/signal/common/download.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,6 @@ func (r *downloadController) Reconcile(ctx context.Context, req cr.Request) (cr.

} else {
logger.Infof("Download of '%s' successful", manifest.URL)

// When the download is complete move the status to the success state
signalData.Status = apsigv2.NewStatus(manifest.SuccessState)
}
Expand Down
17 changes: 5 additions & 12 deletions pkg/autopilot/controller/signal/k0s/apply.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@ import (
"context"
"errors"
"fmt"
"net/url"
"os"
"path"
"path/filepath"

apcomm "github.com/k0sproject/k0s/pkg/autopilot/common"
apconst "github.com/k0sproject/k0s/pkg/autopilot/constant"
apdel "github.com/k0sproject/k0s/pkg/autopilot/controller/delegate"
apsigpred "github.com/k0sproject/k0s/pkg/autopilot/controller/signal/common/predicate"
apsigv2 "github.com/k0sproject/k0s/pkg/autopilot/signaling/v2"
Expand Down Expand Up @@ -102,30 +102,23 @@ func (r *applyingUpdate) Reconcile(ctx context.Context, req cr.Request) (cr.Resu
}

logger := r.log.WithField("signalnode", signalNode.GetName())
logger.Info("Applying update")

var signalData apsigv2.SignalData
if err := signalData.Unmarshal(signalNode.GetAnnotations()); err != nil {
return cr.Result{}, fmt.Errorf("unable to unmarshal signal data for node='%s': %w", req.NamespacedName.Name, err)
}

// Get the filename fragment from the URL
updateURL, err := url.Parse(signalData.Command.K0sUpdate.URL)
if err != nil {
return cr.Result{}, fmt.Errorf("unable to get update request URL: %w", err)
}

// TODO: make the filename part random
updateFilename := path.Base(updateURL.Path)
updateFilenamePath := path.Join(r.k0sBinaryDir, updateFilename)
updateFilenamePath := path.Join(r.k0sBinaryDir, apconst.K0sTempFilename)

// Ensure that the expected file exists
if _, err := os.Stat(updateFilenamePath); errors.Is(err, os.ErrNotExist) {
return cr.Result{}, fmt.Errorf("unable to find update file '%s': %w", updateFilename, err)
return cr.Result{}, fmt.Errorf("unable to find update file '%s': %w", apconst.K0sTempFilename, err)
}

// Ensure that the new file is executable
if err := os.Chmod(updateFilenamePath, 0755); err != nil {
return cr.Result{}, fmt.Errorf("unable to chmod update file '%s': %w", updateFilename, err)
return cr.Result{}, fmt.Errorf("unable to chmod update file '%s': %w", apconst.K0sTempFilename, err)
}

// Perform the update atomically
Expand Down
3 changes: 3 additions & 0 deletions pkg/autopilot/controller/signal/k0s/download.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,10 @@ package k0s

import (
"crypto/sha256"
"path/filepath"

apcomm "github.com/k0sproject/k0s/pkg/autopilot/common"
apconst "github.com/k0sproject/k0s/pkg/autopilot/constant"
apdel "github.com/k0sproject/k0s/pkg/autopilot/controller/delegate"
apsigcomm "github.com/k0sproject/k0s/pkg/autopilot/controller/signal/common"
apsigpred "github.com/k0sproject/k0s/pkg/autopilot/controller/signal/common/predicate"
Expand Down Expand Up @@ -88,6 +90,7 @@ func (b downloadManifestBuilderK0s) Build(signalNode crcli.Object, signalData ap
ExpectedHash: signalData.Command.K0sUpdate.Sha256,
Hasher: sha256.New(),
DownloadDir: b.k0sBinaryDir,
Filename: filepath.Join(b.k0sBinaryDir, apconst.K0sTempFilename),
},
SuccessState: Cordoning,
}
Expand Down
10 changes: 10 additions & 0 deletions pkg/autopilot/download/downloader.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ type Config struct {
ExpectedHash string
Hasher hash.Hash
DownloadDir string
Filename string
}

type downloader struct {
Expand Down Expand Up @@ -72,6 +73,15 @@ func (d *downloader) Download(ctx context.Context) error {
dlreq.SetChecksum(d.config.Hasher, expectedHash, true)
}

// We're never really resuming downloads, so disable this feature.
// This also allows to re-download the file if it's already present.
dlreq.NoResume = true

if d.config.Filename != "" {
d.logger.Infof("Setting filename to %s", d.config.Filename)
dlreq.Filename = d.config.Filename
}

client := grab.NewClient()
// Set user agent to mitigate 403 errors from GitHub
// See https://github.com/cavaliergopher/grab/issues/104
Expand Down

0 comments on commit 76b87d4

Please sign in to comment.