installer: Add support for cached repository

This commit is contained in:
Daniele Rondina
2020-01-12 23:31:43 +01:00
parent aeea0cc5fe
commit c9b684523f
5 changed files with 104 additions and 36 deletions

View File

@@ -18,8 +18,11 @@ package helpers
import ( import (
"io" "io"
"os" "os"
//"os/user"
//"strconv"
"github.com/docker/docker/pkg/archive" "github.com/docker/docker/pkg/archive"
//"github.com/docker/docker/pkg/idtools"
) )
func Tar(src, dest string) error { func Tar(src, dest string) error {
@@ -55,8 +58,25 @@ func Untar(src, dest string, sameOwner bool) error {
} }
defer in.Close() defer in.Close()
return archive.Untar(in, dest, &archive.TarOptions{ opts := &archive.TarOptions{
NoLchown: !sameOwner, // NOTE: NoLchown boolean is used for chmod of the symlink
// Probably it's needed set this always to true.
NoLchown: true,
ExcludePatterns: []string{"dev/"}, // prevent 'operation not permitted' ExcludePatterns: []string{"dev/"}, // prevent 'operation not permitted'
}) }
/*
u, err := user.Current()
if err != nil {
return err
}
// TODO: This seems not sufficient for untar with normal user.
if u.Uid != "0" {
uid, _ := strconv.Atoi(u.Uid)
gid, _ := strconv.Atoi(u.Gid)
opts.ChownOpts = &idtools.Identity{UID: uid, GID: gid}
}
*/
return archive.Untar(in, dest, opts)
} }

View File

@@ -49,15 +49,16 @@ func (c *HttpClient) DownloadArtifact(artifact compiler.Artifact) (compiler.Arti
if err != nil { if err != nil {
return nil, err return nil, err
} }
defer os.RemoveAll(temp)
for _, uri := range c.RepoData.Urls {
Info("Downloading artifact", artifactName, "from", uri)
file, err = ioutil.TempFile(temp, "HttpClient") file, err = ioutil.TempFile(temp, "HttpClient")
if err != nil { if err != nil {
continue return nil, err
} }
for _, uri := range c.RepoData.Urls {
Info("Downloading artifact", artifactName, "from", uri)
u, err = url.Parse(uri) u, err = url.Parse(uri)
if err != nil { if err != nil {
continue continue
@@ -103,7 +104,6 @@ func (c *HttpClient) DownloadFile(name string) (string, error) {
if err != nil { if err != nil {
continue continue
} }
//defer os.Remove(file.Name())
u, err = url.Parse(uri) u, err = url.Parse(uri)
if err != nil { if err != nil {
continue continue

View File

@@ -128,7 +128,7 @@ func (l *LuetInstaller) SyncRepositories(inMemory bool) (Repositories, error) {
defer SpinnerStop() defer SpinnerStop()
syncedRepos := Repositories{} syncedRepos := Repositories{}
for _, r := range l.PackageRepositories { for _, r := range l.PackageRepositories {
repo, err := r.Sync() repo, err := r.Sync(false)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "Failed syncing repository: "+r.GetName()) return nil, errors.Wrap(err, "Failed syncing repository: "+r.GetName())
} }

View File

@@ -48,7 +48,7 @@ type Repository interface {
GetTree() tree.Builder GetTree() tree.Builder
SetTree(tree.Builder) SetTree(tree.Builder)
Write(path string, resetRevision bool) error Write(path string, resetRevision bool) error
Sync() (Repository, error) Sync(bool) (Repository, error)
GetTreePath() string GetTreePath() string
SetTreePath(string) SetTreePath(string)
GetType() string GetType() string

View File

@@ -26,15 +26,16 @@ import (
"strings" "strings"
"time" "time"
"github.com/mudler/luet/pkg/installer/client"
"github.com/ghodss/yaml"
"github.com/mudler/luet/pkg/compiler" "github.com/mudler/luet/pkg/compiler"
"github.com/mudler/luet/pkg/config" "github.com/mudler/luet/pkg/config"
"github.com/mudler/luet/pkg/helpers" "github.com/mudler/luet/pkg/helpers"
"github.com/mudler/luet/pkg/installer/client"
. "github.com/mudler/luet/pkg/logger" . "github.com/mudler/luet/pkg/logger"
pkg "github.com/mudler/luet/pkg/package" pkg "github.com/mudler/luet/pkg/package"
tree "github.com/mudler/luet/pkg/tree" tree "github.com/mudler/luet/pkg/tree"
"github.com/ghodss/yaml"
. "github.com/logrusorgru/aurora"
"github.com/pkg/errors" "github.com/pkg/errors"
) )
@@ -74,7 +75,7 @@ func GenerateRepository(name, descr, t string, urls []string, priority int, src,
} }
return NewLuetSystemRepository( return NewLuetSystemRepository(
config.NewLuetRepository(name, t, descr, urls, priority, true), config.NewLuetRepository(name, t, descr, urls, priority, true, false),
art, tr), nil art, tr), nil
} }
@@ -106,6 +107,7 @@ func NewLuetSystemRepositoryFromYaml(data []byte, db pkg.PackageDatabase) (Repos
p.Urls, p.Urls,
p.Priority, p.Priority,
true, true,
false,
), ),
} }
if p.Revision > 0 { if p.Revision > 0 {
@@ -288,50 +290,96 @@ func (r *LuetSystemRepository) Client() Client {
return nil return nil
} }
func (r *LuetSystemRepository) Sync() (Repository, error) { func (r *LuetSystemRepository) Sync(force bool) (Repository, error) {
Debug("Sync of the repository", r.Name, "in progress..") var repoUpdated bool = false
var treefs string
Debug("Sync of the repository", r.Name, "in progress...")
c := r.Client() c := r.Client()
if c == nil { if c == nil {
return nil, errors.New("No client could be generated from repository.") return nil, errors.New("No client could be generated from repository.")
} }
// Retrieve remote repository.yaml for retrieve revision and date
file, err := c.DownloadFile(REPOSITORY_SPECFILE) file, err := c.DownloadFile(REPOSITORY_SPECFILE)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "While downloading "+REPOSITORY_SPECFILE) return nil, errors.Wrap(err, "While downloading "+REPOSITORY_SPECFILE)
} }
repo, err := r.ReadSpecFile(file, true)
repobasedir := helpers.GetRepoDatabaseDirPath(r.GetName())
repo, err := r.ReadSpecFile(file, false)
if err != nil { if err != nil {
return nil, err return nil, err
} }
// Remove temporary file that contains repository.html.
// Example: /tmp/HttpClient236052003
defer os.RemoveAll(file)
if r.Cached {
if !force {
localRepo, _ := r.ReadSpecFile(filepath.Join(repobasedir, REPOSITORY_SPECFILE), false)
if localRepo != nil {
if localRepo.GetRevision() == repo.GetRevision() &&
localRepo.GetLastUpdate() == repo.GetLastUpdate() {
repoUpdated = true
}
}
}
if r.GetTreePath() == "" {
treefs = filepath.Join(repobasedir, "treefs")
} else {
treefs = r.GetTreePath()
}
} else {
treefs, err = ioutil.TempDir(os.TempDir(), "treefs")
if err != nil {
return nil, errors.Wrap(err, "Error met while creating tempdir for rootfs")
}
}
if !repoUpdated {
archivetree, err := c.DownloadFile(TREE_TARBALL) archivetree, err := c.DownloadFile(TREE_TARBALL)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "While downloading "+TREE_TARBALL) return nil, errors.Wrap(err, "While downloading "+TREE_TARBALL)
} }
defer os.RemoveAll(archivetree) // clean up defer os.RemoveAll(archivetree) // clean up
treefs, err := ioutil.TempDir(os.TempDir(), "treefs") Debug("Tree tarball for the repository " + r.GetName() + " downloaded correctly.")
if r.Cached {
// Copy updated repository.yaml file to repo dir now that the tree is synced.
err = helpers.CopyFile(file, filepath.Join(repobasedir, REPOSITORY_SPECFILE))
if err != nil { if err != nil {
return nil, errors.Wrap(err, "Error met while creating tempdir for rootfs") return nil, errors.Wrap(err, "Error on update "+REPOSITORY_SPECFILE)
} }
//defer os.RemoveAll(treefs) // clean up // Remove previous tree
os.RemoveAll(treefs)
// TODO: Following as option if archive as output? }
// archive, err := ioutil.TempDir(os.TempDir(), "archive") Debug("Untar tree of the repository " + r.Name + "...")
// if err != nil { err = helpers.Untar(archivetree, treefs, true)
// return nil, errors.Wrap(err, "Error met while creating tempdir for rootfs")
// }
// defer os.RemoveAll(archive) // clean up
err = helpers.Untar(archivetree, treefs, false)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "Error met while unpacking rootfs") return nil, errors.Wrap(err, "Error met while unpacking rootfs")
} }
tsec, _ := strconv.ParseInt(repo.GetLastUpdate(), 10, 64)
InfoC(
Bold(Red(":house: Repository "+r.GetName()+" revision: ")).String() +
Bold(Green(repo.GetRevision())).String() + " - " +
Bold(Green(time.Unix(tsec, 0).String())).String(),
)
} else {
Info("Repository", r.GetName(), "is already up to date.")
}
reciper := tree.NewInstallerRecipe(pkg.NewInMemoryDatabase(false)) reciper := tree.NewInstallerRecipe(pkg.NewInMemoryDatabase(false))
err = reciper.Load(treefs) err = reciper.Load(treefs)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "Error met while unpacking rootfs") return nil, errors.Wrap(err, "Error met while unpacking rootfs")
} }
repo.SetTree(reciper) repo.SetTree(reciper)
repo.SetTreePath(treefs) repo.SetTreePath(treefs)
repo.SetUrls(r.GetUrls()) repo.SetUrls(r.GetUrls())