internal/artifact/upgrade.go (41 lines of code) (raw):
package artifact
import (
"bytes"
"crypto/sha256"
"fmt"
"io"
"io/fs"
"os"
"github.com/pkg/errors"
"go.uber.org/zap"
)
// checksumMatch compares the checksum of the installed artifact with the expected checksum
// A mismatch of checksum indicates installed artifacts are due for an upgrade
func checksumMatch(installedArtifactPath string, src Source) (bool, error) {
fh, err := os.Open(installedArtifactPath)
if err != nil {
return false, errors.Wrap(err, "checking for checksum match")
}
defer fh.Close()
digest := sha256.New()
if _, err = io.Copy(digest, fh); err != nil {
return false, errors.Wrapf(err, "calculating sha256 for %s", installedArtifactPath)
}
return bytes.Equal(digest.Sum(nil), src.ExpectedChecksum()), nil
}
// Upgrade upgrades an artifact from the source only if the expected checksum doesn't match with the
// checksum of artifact already installed.
func Upgrade(artifactName, path string, source Source, perms fs.FileMode, log *zap.Logger) error {
match, err := checksumMatch(path, source)
if err != nil {
return err
}
if !match {
if err := InstallFile(path, source, perms); err != nil {
return errors.Wrapf(err, "installing %s", artifactName)
}
if !source.VerifyChecksum() {
return errors.Wrapf(NewChecksumError(source), "verifying checksum post installing %s", artifactName)
}
log.Info("Upgraded", zap.String("artifact", artifactName))
} else {
log.Info(fmt.Sprintf("No new version found for artifact %s. Skipping upgrade.", artifactName))
}
return nil
}