Improve updatemgr and updates module
This commit is contained in:
@@ -82,7 +82,7 @@ func (d *Downloader) getIndex(ctx context.Context, url string) (indexData []byte
|
||||
}
|
||||
|
||||
// Verify and parse index.
|
||||
bundle, err = ParseIndex(indexData, d.u.cfg.Verify)
|
||||
bundle, err = ParseIndex(indexData, d.u.cfg.Platform, d.u.cfg.Verify)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("parse index: %w", err)
|
||||
}
|
||||
@@ -206,14 +206,14 @@ func (d *Downloader) getArtifact(ctx context.Context, artifact *Artifact, url st
|
||||
// TODO: Normally we should do operations on "untrusted" data _after_ verification,
|
||||
// but we really want the checksum to be for the unpacked data. Should we add another checksum, or is HTTPS enough?
|
||||
if artifact.Unpack != "" {
|
||||
artifactData, err = decompress(artifact.Unpack, artifactData)
|
||||
artifactData, err = Decompress(artifact.Unpack, artifactData)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("decompress: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Verify checksum.
|
||||
if err := checkSHA256Sum(artifactData, artifact.SHA256); err != nil {
|
||||
if err := CheckSHA256Sum(artifactData, artifact.SHA256); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -250,7 +250,8 @@ func (d *Downloader) downloadData(ctx context.Context, url string) ([]byte, erro
|
||||
return content, nil
|
||||
}
|
||||
|
||||
func decompress(cType string, fileBytes []byte) ([]byte, error) {
|
||||
// Decompress decompresses the given data according to the specified type.
|
||||
func Decompress(cType string, fileBytes []byte) ([]byte, error) {
|
||||
switch cType {
|
||||
case "zip":
|
||||
return decompressZip(fileBytes)
|
||||
|
||||
@@ -121,7 +121,8 @@ type Index struct {
|
||||
}
|
||||
|
||||
// LoadIndex loads and parses an index from the given filename.
|
||||
func LoadIndex(filename string, trustStore jess.TrustStore) (*Index, error) {
|
||||
// Leave platform empty to use current platform.
|
||||
func LoadIndex(filename string, platform string, trustStore jess.TrustStore) (*Index, error) {
|
||||
// Read index file from disk.
|
||||
content, err := os.ReadFile(filename)
|
||||
if err != nil {
|
||||
@@ -129,11 +130,12 @@ func LoadIndex(filename string, trustStore jess.TrustStore) (*Index, error) {
|
||||
}
|
||||
|
||||
// Parse and return.
|
||||
return ParseIndex(content, trustStore)
|
||||
return ParseIndex(content, platform, trustStore)
|
||||
}
|
||||
|
||||
// ParseIndex parses an index from a json string.
|
||||
func ParseIndex(jsonContent []byte, trustStore jess.TrustStore) (*Index, error) {
|
||||
// Leave platform empty to use current platform.
|
||||
func ParseIndex(jsonContent []byte, platform string, trustStore jess.TrustStore) (*Index, error) {
|
||||
// Verify signature.
|
||||
if trustStore != nil {
|
||||
if err := filesig.VerifyJSONSignature(jsonContent, trustStore); err != nil {
|
||||
@@ -148,8 +150,13 @@ func ParseIndex(jsonContent []byte, trustStore jess.TrustStore) (*Index, error)
|
||||
return nil, fmt.Errorf("parse index: %w", err)
|
||||
}
|
||||
|
||||
// Check platform.
|
||||
if platform == "" {
|
||||
platform = currentPlatform
|
||||
}
|
||||
|
||||
// Initialize data.
|
||||
err = index.init()
|
||||
err = index.init(platform)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -157,7 +164,7 @@ func ParseIndex(jsonContent []byte, trustStore jess.TrustStore) (*Index, error)
|
||||
return index, nil
|
||||
}
|
||||
|
||||
func (index *Index) init() error {
|
||||
func (index *Index) init(platform string) error {
|
||||
// Parse version number, if set.
|
||||
if index.Version != "" {
|
||||
versionNum, err := semver.NewVersion(index.Version)
|
||||
@@ -167,10 +174,10 @@ func (index *Index) init() error {
|
||||
index.versionNum = versionNum
|
||||
}
|
||||
|
||||
// Filter artifacts by current platform.
|
||||
// Filter artifacts by platform.
|
||||
filtered := make([]*Artifact, 0)
|
||||
for _, a := range index.Artifacts {
|
||||
if a.Platform == "" || a.Platform == currentPlatform {
|
||||
if a.Platform == "" || a.Platform == platform {
|
||||
filtered = append(filtered, a)
|
||||
}
|
||||
}
|
||||
@@ -248,7 +255,7 @@ func (index *Index) ShouldUpgradeTo(newIndex *Index) error {
|
||||
// VerifyArtifacts checks if all artifacts are present in the given dir and have the correct hash.
|
||||
func (index *Index) VerifyArtifacts(dir string) error {
|
||||
for _, artifact := range index.Artifacts {
|
||||
err := checkSHA256SumFile(filepath.Join(dir, artifact.Filename), artifact.SHA256)
|
||||
err := CheckSHA256SumFile(filepath.Join(dir, artifact.Filename), artifact.SHA256)
|
||||
if err != nil {
|
||||
return fmt.Errorf("verify %s: %w", artifact.Filename, err)
|
||||
}
|
||||
@@ -283,7 +290,8 @@ func (index *Index) Export(signingKey *jess.Signet, trustStore jess.TrustStore)
|
||||
return signedIndex, nil
|
||||
}
|
||||
|
||||
func checkSHA256SumFile(filename string, sha256sum string) error {
|
||||
// CheckSHA256SumFile checks the sha256sum of the given file.
|
||||
func CheckSHA256SumFile(filename string, sha256sum string) error {
|
||||
// Check expected hash.
|
||||
expectedDigest, err := hex.DecodeString(sha256sum)
|
||||
if err != nil {
|
||||
@@ -312,7 +320,8 @@ func checkSHA256SumFile(filename string, sha256sum string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func checkSHA256Sum(fileData []byte, sha256sum string) error {
|
||||
// CheckSHA256Sum checks the sha256sum of the given data.
|
||||
func CheckSHA256Sum(fileData []byte, sha256sum string) error {
|
||||
// Check expected hash.
|
||||
expectedDigest, err := hex.DecodeString(sha256sum)
|
||||
if err != nil {
|
||||
|
||||
@@ -253,7 +253,7 @@ func GenerateIndexFromDir(sourceDir string, cfg IndexScanConfig) (*Index, error)
|
||||
export := make([]*Artifact, 0, len(artifacts))
|
||||
for _, artifact := range artifacts {
|
||||
// Compute hash.
|
||||
hash, err := getSHA256(artifact.localFile, artifact.Unpack)
|
||||
hash, err := GetSHA256(artifact.localFile, artifact.Unpack)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("calculate hash of file: %s %w", artifact.localFile, err)
|
||||
}
|
||||
@@ -294,7 +294,8 @@ func GenerateIndexFromDir(sourceDir string, cfg IndexScanConfig) (*Index, error)
|
||||
return index, nil
|
||||
}
|
||||
|
||||
func getSHA256(path string, unpackType string) (string, error) {
|
||||
// GetSHA256 gets the sha256sum of the given file and unpacks it if necessary.
|
||||
func GetSHA256(path string, unpackType string) (string, error) {
|
||||
content, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
return "", err
|
||||
@@ -302,7 +303,7 @@ func getSHA256(path string, unpackType string) (string, error) {
|
||||
|
||||
// Decompress if compression was applied to the file.
|
||||
if unpackType != "" {
|
||||
content, err = decompress(unpackType, content)
|
||||
content, err = Decompress(unpackType, content)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
@@ -68,6 +68,8 @@ type Config struct {
|
||||
IndexFile string
|
||||
// Verify enables and specifies the trust the index signatures will be checked against.
|
||||
Verify jess.TrustStore
|
||||
// Platform defines the platform to download artifacts for. Defaults to current platform.
|
||||
Platform string
|
||||
|
||||
// AutoCheck defines that new indexes may be downloaded automatically without outside trigger.
|
||||
AutoCheck bool
|
||||
@@ -116,6 +118,11 @@ func (cfg *Config) Check() error {
|
||||
}
|
||||
}
|
||||
|
||||
// Check platform.
|
||||
if cfg.Platform == "" {
|
||||
cfg.Platform = currentPlatform
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -168,7 +175,7 @@ func New(instance instance, name string, cfg Config) (*Updater, error) {
|
||||
module.upgradeWorkerMgr = m.NewWorkerMgr("upgrader", module.upgradeWorker, nil)
|
||||
|
||||
// Load index.
|
||||
index, err := LoadIndex(filepath.Join(cfg.Directory, cfg.IndexFile), cfg.Verify)
|
||||
index, err := LoadIndex(filepath.Join(cfg.Directory, cfg.IndexFile), cfg.Platform, cfg.Verify)
|
||||
if err == nil {
|
||||
// Verify artifacts.
|
||||
if err := index.VerifyArtifacts(cfg.Directory); err != nil {
|
||||
@@ -186,7 +193,7 @@ func New(instance instance, name string, cfg Config) (*Updater, error) {
|
||||
module.corruptedInstallation = fmt.Errorf("invalid index: %w", err)
|
||||
}
|
||||
index, err = GenerateIndexFromDir(cfg.Directory, IndexScanConfig{Version: "0.0.0"})
|
||||
if err == nil && index.init() == nil {
|
||||
if err == nil && index.init(currentPlatform) == nil {
|
||||
module.index = index
|
||||
return module, nil
|
||||
}
|
||||
@@ -214,7 +221,7 @@ func (u *Updater) updateAndUpgrade(w *mgr.WorkerCtx, indexURLs []string, ignoreV
|
||||
}
|
||||
} else {
|
||||
// Otherwise, load index from download dir.
|
||||
downloader.index, err = LoadIndex(filepath.Join(u.cfg.DownloadDirectory, u.cfg.IndexFile), u.cfg.Verify)
|
||||
downloader.index, err = LoadIndex(filepath.Join(u.cfg.DownloadDirectory, u.cfg.IndexFile), u.cfg.Platform, u.cfg.Verify)
|
||||
if err != nil {
|
||||
return fmt.Errorf("load previously downloaded index file: %w", err)
|
||||
}
|
||||
@@ -573,7 +580,7 @@ func (u *Updater) GetFiles() ([]*Artifact, error) {
|
||||
export := make([]*Artifact, 0, len(u.index.Artifacts))
|
||||
for _, artifact := range u.index.Artifacts {
|
||||
switch {
|
||||
case artifact.Platform != "" && artifact.Platform != currentPlatform:
|
||||
case artifact.Platform != "" && artifact.Platform != u.cfg.Platform:
|
||||
// Platform is defined and does not match.
|
||||
// Platforms are usually pre-filtered, but just to be sure.
|
||||
default:
|
||||
@@ -604,7 +611,7 @@ func (u *Updater) GetFile(name string) (*Artifact, error) {
|
||||
switch {
|
||||
case artifact.Filename != name:
|
||||
// Name does not match.
|
||||
case artifact.Platform != "" && artifact.Platform != currentPlatform:
|
||||
case artifact.Platform != "" && artifact.Platform != u.cfg.Platform:
|
||||
// Platform is defined and does not match.
|
||||
// Platforms are usually pre-filtered, but just to be sure.
|
||||
default:
|
||||
|
||||
@@ -84,7 +84,7 @@ func TestPerformUpdate(t *testing.T) {
|
||||
}
|
||||
if data, err := os.ReadFile(filepath.Join(updateDir, "index.json")); err == nil {
|
||||
fmt.Println(string(data))
|
||||
idx, err := ParseIndex(data, nil)
|
||||
idx, err := ParseIndex(data, updater.cfg.Platform, nil)
|
||||
if err == nil {
|
||||
fmt.Println(idx.Version)
|
||||
fmt.Println(idx.versionNum)
|
||||
@@ -97,7 +97,7 @@ func TestPerformUpdate(t *testing.T) {
|
||||
})
|
||||
|
||||
// Check if the current version is now the new.
|
||||
newIndex, err := LoadIndex(filepath.Join(installedDir, "index.json"), nil)
|
||||
newIndex, err := LoadIndex(filepath.Join(installedDir, "index.json"), updater.cfg.Platform, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user