Compare commits

...

5 Commits

Author SHA1 Message Date
Ettore Di Giacinto
4d60795fdc Tag 0.19.1 2021-10-22 18:44:42 +02:00
Ettore Di Giacinto
6b45b1d61c ux: rework displaying of success messages 2021-10-22 17:55:38 +02:00
Ettore Di Giacinto
5eb5a42bf7 Generate snapshot and push it along
Fixes #260
Fixes #223
2021-10-22 17:55:08 +02:00
Ettore Di Giacinto
0bacdc75f2 Allow clients to pick a specific referenceID
Related to #260
2021-10-22 12:39:36 +02:00
Ettore Di Giacinto
917d0935ad Show progressbar only if terminal is big enough
Fixes #259

The bug is caused by
4c725e56bf/progressbar_printer.go (L190)
which is not taking into account when barCurrentLength is <=0.

As a workaround display it only if the terminal width is big enough.

Now the context drives this kind of runtime state, so we keep everything
tight and we inject only that into the workers
2021-10-22 12:39:07 +02:00
11 changed files with 315 additions and 60 deletions

View File

@@ -30,7 +30,7 @@ var cfgFile string
var Verbose bool
const (
LuetCLIVersion = "0.19.0"
LuetCLIVersion = "0.19.1"
LuetEnvPrefix = "LUET"
)

View File

@@ -28,9 +28,11 @@ import (
"github.com/kyokomi/emoji"
"github.com/mudler/luet/pkg/helpers/terminal"
"github.com/pkg/errors"
"github.com/pterm/pterm"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
"golang.org/x/term"
)
const (
@@ -48,13 +50,16 @@ type Context struct {
NoSpinner bool
s *pterm.SpinnerPrinter
spinnerLock sync.Mutex
spinnerLock *sync.Mutex
z *zap.Logger
AreaPrinter *pterm.AreaPrinter
ProgressBar *pterm.ProgressbarPrinter
}
func NewContext() *Context {
return &Context{
IsTerminal: terminal.IsTerminal(os.Stdout),
spinnerLock: &sync.Mutex{},
IsTerminal: terminal.IsTerminal(os.Stdout),
Config: &LuetConfig{
ConfigFromHost: true,
Logging: LuetLoggingConfig{},
@@ -68,6 +73,35 @@ func NewContext() *Context {
}
}
func (c *Context) Copy() *Context {
configCopy := *c.Config
configCopy.System = *c.Config.GetSystem()
configCopy.General = *c.Config.GetGeneral()
configCopy.Logging = *c.Config.GetLogging()
ctx := *c
ctxCopy := &ctx
ctxCopy.Config = &configCopy
return ctxCopy
}
// GetTerminalSize returns the width and the height of the active terminal.
func (c *Context) GetTerminalSize() (width, height int, err error) {
w, h, err := term.GetSize(int(os.Stdout.Fd()))
if w <= 0 {
w = 0
}
if h <= 0 {
h = 0
}
if err != nil {
err = errors.New("size not detectable")
}
return w, h, err
}
func (c *Context) Init() (err error) {
if c.IsTerminal {
if !c.Config.Logging.Color {

View File

@@ -37,6 +37,8 @@ type LuetRepository struct {
Verify bool `json:"verify,omitempty" yaml:"verify,omitempty" mapstructure:"verify"`
Arch string `json:"arch,omitempty" yaml:"arch,omitempty" mapstructure:"arch"`
ReferenceID string `json:"reference,omitempty" yaml:"reference,omitempty" mapstructure:"reference"`
// Incremented value that identify revision of the repository in a user-friendly way.
Revision int `json:"revision,omitempty" yaml:"-" mapstructure:"-"`
// Epoch time in seconds

View File

@@ -56,7 +56,7 @@ func (s *SimpleDocker) BuildImage(opts Options) error {
return err
}
s.ctx.Info(":whale: Building image " + name + " done")
s.ctx.Success(":whale: Building image " + name + " done")
bus.Manager.Publish(bus.EventImagePostBuild, opts)
@@ -70,7 +70,7 @@ func (s *SimpleDocker) CopyImage(src, dst string) error {
if err != nil {
return errors.Wrap(err, "Failed tagging image: "+string(out))
}
s.ctx.Info(":whale: Tagged image:", src, "->", dst)
s.ctx.Success(":whale: Tagged image:", src, "->", dst)
return nil
}
@@ -90,7 +90,7 @@ func (s *SimpleDocker) DownloadImage(opts Options) error {
return errors.Wrap(err, "Failed pulling image: "+string(out))
}
s.ctx.Info(":whale: Downloaded image:", name)
s.ctx.Success(":whale: Downloaded image:", name)
bus.Manager.Publish(bus.EventImagePostPull, opts)
return nil
@@ -120,7 +120,7 @@ func (s *SimpleDocker) RemoveImage(opts Options) error {
if err != nil {
return errors.Wrap(err, "Failed removing image: "+string(out))
}
s.ctx.Info(":whale: Removed image:", name)
s.ctx.Success(":whale: Removed image:", name)
//Info(string(out))
return nil
}
@@ -137,7 +137,7 @@ func (s *SimpleDocker) Push(opts Options) error {
if err != nil {
return errors.Wrap(err, "Failed pushing image: "+string(out))
}
s.ctx.Info(":whale: Pushed image:", name)
s.ctx.Success(":whale: Pushed image:", name)
bus.Manager.Publish(bus.EventImagePostPush, opts)
//Info(string(out))

View File

@@ -447,7 +447,7 @@ func (cs *LuetCompiler) genArtifact(p *compilerspec.LuetCompilationSpec, builder
if err != nil {
return a, errors.Wrap(err, "Failed while writing metadata file")
}
cs.Options.Context.Info(pkgTag, " :white_check_mark: done (empty virtual package)")
cs.Options.Context.Success(pkgTag, " :white_check_mark: done (empty virtual package)")
return a, nil
}
@@ -477,7 +477,7 @@ func (cs *LuetCompiler) genArtifact(p *compilerspec.LuetCompilationSpec, builder
if err != nil {
return a, errors.Wrap(err, "Failed while writing metadata file")
}
cs.Options.Context.Info(pkgTag, " :white_check_mark: Done")
cs.Options.Context.Success(pkgTag, " :white_check_mark: Done")
return a, nil
}
@@ -965,7 +965,7 @@ func (cs *LuetCompiler) resolveMultiStageImages(concurrency int, keepPermissions
Source: c.Source,
Destination: c.Destination,
})
cs.Options.Context.Info(copyTag2, ":white_check_mark: Done")
cs.Options.Context.Success(copyTag2, ":white_check_mark: Done")
} else {
resolvedCopyFields = append(resolvedCopyFields, c)
}
@@ -1128,7 +1128,7 @@ func (cs *LuetCompiler) compile(concurrency int, keepPermissions bool, generateF
a.PackageCacheImage = assertion.Hash.PackageHash
cs.Options.Context.Info(pkgTag, ":white_check_mark: Done")
cs.Options.Context.Success(pkgTag, ":white_check_mark: Done")
bus.Manager.Publish(bus.EventPackagePostBuild, struct {
CompileSpec *compilerspec.LuetCompilationSpec

View File

@@ -38,8 +38,6 @@ type HttpClient struct {
RepoData RepoData
Cache *artifact.ArtifactCache
context *types.Context
ProgressBarArea *pterm.AreaPrinter
}
func NewHttpClient(r RepoData, ctx *types.Context) *HttpClient {
@@ -126,11 +124,16 @@ func (c *HttpClient) DownloadFile(p string) (string, error) {
}
resp := client.Do(req)
pb := pterm.DefaultProgressbar.WithTotal(int(resp.Size()))
if c.ProgressBarArea != nil {
pb = pb.WithPrintTogether(c.ProgressBarArea)
// Initialize a progressbar only if we have one in the current context
var pb *pterm.ProgressbarPrinter
if c.context.ProgressBar != nil {
pb = pterm.DefaultProgressbar.WithTotal(int(resp.Size()))
if c.context.AreaPrinter != nil {
pb = pb.WithPrintTogether(c.context.AreaPrinter)
}
pb, _ = pb.WithTitle(filepath.Base(resp.Request.HTTPRequest.URL.RequestURI())).Start()
}
pb, _ = pb.WithTitle(filepath.Base(resp.Request.HTTPRequest.URL.RequestURI())).Start()
// start download loop
t := time.NewTicker(500 * time.Millisecond)
defer t.Stop()
@@ -140,11 +143,15 @@ func (c *HttpClient) DownloadFile(p string) (string, error) {
for {
select {
case <-t.C:
// bar.Set64(resp.BytesComplete())
//pb.Increment()
pb.Increment().Current = int(resp.BytesComplete())
// update the progress bar
if pb != nil {
pb.Increment().Current = int(resp.BytesComplete())
}
case <-resp.Done:
pb.Increment().Current = int(resp.BytesComplete())
// update the progress bar
if pb != nil {
pb.Increment().Current = int(resp.BytesComplete())
}
// download is complete
break download_loop
}
@@ -157,7 +164,11 @@ func (c *HttpClient) DownloadFile(p string) (string, error) {
c.context.Info("Downloaded", p, "of",
fmt.Sprintf("%.2f", (float64(resp.BytesComplete())/1000)/1000), "MB (",
fmt.Sprintf("%.2f", (float64(resp.BytesPerSecond())/1024)/1024), "MiB/s )")
pb.Stop()
if pb != nil {
// stop the progressbar if active
pb.Stop()
}
//bar.Finish()
downloaded = true
break

View File

@@ -32,7 +32,6 @@ import (
"github.com/mudler/luet/pkg/helpers"
fileHelper "github.com/mudler/luet/pkg/helpers/file"
"github.com/mudler/luet/pkg/helpers/match"
"github.com/mudler/luet/pkg/installer/client"
pkg "github.com/mudler/luet/pkg/package"
"github.com/mudler/luet/pkg/solver"
"github.com/pterm/pterm"
@@ -566,21 +565,30 @@ func (l *LuetInstaller) download(syncedRepos Repositories, toDownload map[string
var wg = new(sync.WaitGroup)
area, _ := pterm.DefaultArea.Start()
ctx := l.Options.Context.Copy()
p, _ := pterm.DefaultProgressbar.WithPrintTogether(area).WithTotal(len(toDownload)).WithTitle("Downloading packages").Start()
// Check if the terminal is big enough to display a progress bar
// https://github.com/pterm/pterm/blob/4c725e56bfd9eb38e1c7b9dec187b50b93baa8bd/progressbar_printer.go#L190
w, _, err := ctx.GetTerminalSize()
if ctx.IsTerminal && err == nil && w > 100 {
area, _ := pterm.DefaultArea.Start()
p, _ := pterm.DefaultProgressbar.WithPrintTogether(area).WithTotal(len(toDownload)).WithTitle("Downloading packages").Start()
ctx.AreaPrinter = area
ctx.ProgressBar = p
defer area.Stop()
}
// Download
for i := 0; i < l.Options.Concurrency; i++ {
wg.Add(1)
go l.downloadWorker(i, wg, all, p, area)
go l.downloadWorker(i, wg, all, ctx)
}
for _, c := range toDownload {
all <- c
}
close(all)
wg.Wait()
area.Stop()
return nil
}
@@ -772,7 +780,7 @@ func (l *LuetInstaller) checkFileconflicts(toInstall map[string]ArtifactMatch, c
filesToInstall := []string{}
for _, m := range toInstall {
a, err := l.downloadPackage(m, nil)
a, err := l.downloadPackage(m, l.Options.Context)
if err != nil && !l.Options.Force {
return errors.Wrap(err, "Failed downloading package")
}
@@ -867,14 +875,9 @@ func (l *LuetInstaller) install(o Option, syncedRepos Repositories, toInstall ma
return s.ExecuteFinalizers(l.Options.Context, toFinalize)
}
func (l *LuetInstaller) downloadPackage(a ArtifactMatch, area *pterm.AreaPrinter) (*artifact.PackageArtifact, error) {
func (l *LuetInstaller) downloadPackage(a ArtifactMatch, ctx *types.Context) (*artifact.PackageArtifact, error) {
cli := a.Repository.Client(l.Options.Context)
switch v := cli.(type) {
case *client.HttpClient:
v.ProgressBarArea = area
}
cli := a.Repository.Client(ctx)
artifact, err := cli.DownloadArtifact(a.Artifact)
if err != nil {
@@ -890,7 +893,7 @@ func (l *LuetInstaller) downloadPackage(a ArtifactMatch, area *pterm.AreaPrinter
func (l *LuetInstaller) installPackage(m ArtifactMatch, s *System) error {
a, err := l.downloadPackage(m, nil)
a, err := l.downloadPackage(m, l.Options.Context)
if err != nil && !l.Options.Force {
return errors.Wrap(err, "Failed downloading package")
}
@@ -910,20 +913,21 @@ func (l *LuetInstaller) installPackage(m ArtifactMatch, s *System) error {
return s.Database.SetPackageFiles(&pkg.PackageFile{PackageFingerprint: m.Package.GetFingerPrint(), Files: files})
}
func (l *LuetInstaller) downloadWorker(i int, wg *sync.WaitGroup, c <-chan ArtifactMatch, pb *pterm.ProgressbarPrinter, area *pterm.AreaPrinter) error {
func (l *LuetInstaller) downloadWorker(i int, wg *sync.WaitGroup, c <-chan ArtifactMatch, ctx *types.Context) error {
defer wg.Done()
for p := range c {
// TODO: Keep trace of what was added from the tar, and save it into system
_, err := l.downloadPackage(p, area)
_, err := l.downloadPackage(p, ctx)
if err != nil {
l.Options.Context.Error("Failed downloading package "+p.Package.GetName(), err.Error())
return errors.Wrap(err, "Failed downloading package "+p.Package.GetName())
} else {
l.Options.Context.Success(":package: Package ", p.Package.HumanReadableString(), "downloaded")
}
pb.Increment()
if ctx.ProgressBar != nil {
ctx.ProgressBar.Increment()
}
}
return nil

View File

@@ -539,6 +539,7 @@ func (r *LuetSystemRepository) AddMetadata(ctx *types.Context, repospec, dst str
if err != nil {
return nil, err
}
a, err := r.AddRepositoryFile(metaTmpDir, REPOFILE_META_KEY, dst, NewDefaultMetaRepositoryFile())
if err != nil {
return a, errors.Wrap(err, "Error met while adding archive to repository")
@@ -558,7 +559,7 @@ func (r *LuetSystemRepository) AddMetadata(ctx *types.Context, repospec, dst str
// AddTree adds a tree.Builder with the given key to the repository.
// It will generate an artifact which will be then embedded in the repository manifest
// It returns the generated artifacts and an error
func (r *LuetSystemRepository) AddTree(ctx *types.Context, t tree.Builder, dst, key string, f LuetRepositoryFile) (*artifact.PackageArtifact, error) {
func (r *LuetSystemRepository) AddTree(ctx *types.Context, t tree.Builder, dst, key string, defaults LuetRepositoryFile) (*artifact.PackageArtifact, error) {
// Create tree and repository file
archive, err := ctx.Config.GetSystem().TempDir("archive")
if err != nil {
@@ -570,13 +571,70 @@ func (r *LuetSystemRepository) AddTree(ctx *types.Context, t tree.Builder, dst,
return nil, errors.Wrap(err, "Error met while saving the tree")
}
a, err := r.AddRepositoryFile(archive, key, dst, f)
a, err := r.AddRepositoryFile(archive, key, dst, defaults)
if err != nil {
return nil, errors.Wrap(err, "Error met while adding archive to repository")
}
return a, nil
}
// Snapshot creates a copy of the current repository index into dst.
// The copy will be prefixed with "id".
// This allows the clients to refer to old versions of the repository by using the reference_id
func (r *LuetSystemRepository) Snapshot(id, dst string) (artifacts []*artifact.PackageArtifact, snapshotIndex string, err error) {
var snapshotFmt string = "%s-%s"
repospec := filepath.Join(dst, REPOSITORY_SPECFILE)
snapshotIndex = filepath.Join(dst, fmt.Sprintf(snapshotFmt, id, REPOSITORY_SPECFILE))
err = fileHelper.CopyFile(repospec, filepath.Join(dst, snapshotIndex))
if err != nil {
err = errors.Wrap(err, "while copying repo spec")
return
}
b, err := ioutil.ReadFile(repospec)
if err != nil {
return
}
newRepoIndex := &LuetSystemRepository{}
err = yaml.Unmarshal(b, newRepoIndex)
if err != nil {
return
}
for _, key := range []string{REPOFILE_META_KEY, REPOFILE_TREE_KEY, REPOFILE_COMPILER_TREE_KEY} {
var luetFile LuetRepositoryFile
luetFile, err = r.GetRepositoryFile(key)
if err != nil {
return
}
newMetaFile := fmt.Sprintf(snapshotFmt, id, luetFile.FileName)
err = fileHelper.CopyFile(filepath.Join(dst, luetFile.FileName), filepath.Join(dst, newMetaFile))
if err != nil {
return
}
m := &luetFile
m.FileName = newMetaFile
newRepoIndex.RepositoryFiles[key] = *m
artifacts = append(artifacts, artifact.NewPackageArtifact(filepath.Join(dst, newMetaFile)))
}
_, serialized := newRepoIndex.Serialize()
data, err := yaml.Marshal(serialized)
if err != nil {
return
}
err = ioutil.WriteFile(snapshotIndex, data, os.ModePerm)
return
}
// AddRepositoryFile adds a path to a key in the repository manifest.
// The path will be compressed, and a default File has to be passed in case there is no entry into
// the repository manifest
@@ -772,6 +830,14 @@ func (r *LuetSystemRepository) SyncBuildMetadata(ctx *types.Context, path string
return nil
}
func (r *LuetSystemRepository) referenceID() string {
repositoryReferenceID := REPOSITORY_SPECFILE
if r.ReferenceID != "" {
repositoryReferenceID = r.ReferenceID
}
return repositoryReferenceID
}
func (r *LuetSystemRepository) Sync(ctx *types.Context, force bool) (*LuetSystemRepository, error) {
var repoUpdated bool = false
var treefs, metafs string
@@ -782,10 +848,12 @@ func (r *LuetSystemRepository) Sync(ctx *types.Context, force bool) (*LuetSystem
return nil, errors.New("no client could be generated from repository")
}
repositoryReferenceID := r.referenceID()
// Retrieve remote repository.yaml for retrieve revision and date
file, err := c.DownloadFile(REPOSITORY_SPECFILE)
file, err := c.DownloadFile(repositoryReferenceID)
if err != nil {
return nil, errors.Wrap(err, "while downloading "+REPOSITORY_SPECFILE)
return nil, errors.Wrap(err, "while downloading "+repositoryReferenceID)
}
repobasedir := ctx.Config.GetSystem().GetRepoDatabaseDirPath(r.GetName())
@@ -799,7 +867,7 @@ func (r *LuetSystemRepository) Sync(ctx *types.Context, force bool) (*LuetSystem
if r.Cached {
if !force {
localRepo, _ := r.ReadSpecFile(filepath.Join(repobasedir, REPOSITORY_SPECFILE))
localRepo, _ := r.ReadSpecFile(filepath.Join(repobasedir, repositoryReferenceID))
if localRepo != nil {
if localRepo.GetRevision() == downloadedRepoMeta.GetRevision() &&
localRepo.GetLastUpdate() == downloadedRepoMeta.GetLastUpdate() {
@@ -850,9 +918,9 @@ func (r *LuetSystemRepository) Sync(ctx *types.Context, force bool) (*LuetSystem
if r.Cached {
// Copy updated repository.yaml file to repo dir now that the tree is synced.
err = fileHelper.CopyFile(file, filepath.Join(repobasedir, REPOSITORY_SPECFILE))
err = fileHelper.CopyFile(file, filepath.Join(repobasedir, repositoryReferenceID))
if err != nil {
return nil, errors.Wrap(err, "Error on update "+REPOSITORY_SPECFILE)
return nil, errors.Wrap(err, "Error on update "+repositoryReferenceID)
}
// Remove previous tree
os.RemoveAll(treefs)

View File

@@ -136,7 +136,7 @@ func (d *dockerRepositoryGenerator) pushFileFromArtifact(a *artifact.PackageArti
return nil
}
func (d *dockerRepositoryGenerator) pushRepoMetadata(repospec string, r *LuetSystemRepository) error {
func (d *dockerRepositoryGenerator) pushRepoMetadata(repospec, tag string, r *LuetSystemRepository) error {
// create temp dir for metafile
metaDir, err := d.context.Config.GetSystem().TempDir("metadata")
if err != nil {
@@ -144,13 +144,13 @@ func (d *dockerRepositoryGenerator) pushRepoMetadata(repospec string, r *LuetSys
}
defer os.RemoveAll(metaDir) // clean up
tempRepoFile := filepath.Join(metaDir, REPOSITORY_SPECFILE+".tar")
tempRepoFile := filepath.Join(metaDir, tag+".tar")
if err := helpers.Tar(repospec, tempRepoFile); err != nil {
return errors.Wrap(err, "Error met while archiving repository file")
}
a := artifact.NewPackageArtifact(tempRepoFile)
imageRepo := fmt.Sprintf("%s:%s", d.imagePrefix, REPOSITORY_SPECFILE)
imageRepo := fmt.Sprintf("%s:%s", d.imagePrefix, tag)
if err := d.pushFileFromArtifact(a, imageRepo); err != nil {
return errors.Wrap(err, "while pushing file from artifact")
@@ -242,14 +242,7 @@ func (d *dockerRepositoryGenerator) Generate(r *LuetSystemRepository, imagePrefi
return errors.Wrap(err, "error met while pushing compiler tree")
}
// create temp dir for metafile
metaDir, err := d.context.Config.GetSystem().TempDir("metadata")
if err != nil {
return errors.Wrap(err, "error met while creating tempdir for metadata")
}
defer os.RemoveAll(metaDir) // clean up
a, err = r.AddMetadata(d.context, repospec, metaDir)
a, err = r.AddMetadata(d.context, repospec, repoTemp)
if err != nil {
return errors.Wrap(err, "failed adding Metadata file to repository")
}
@@ -258,10 +251,28 @@ func (d *dockerRepositoryGenerator) Generate(r *LuetSystemRepository, imagePrefi
return errors.Wrap(err, "error met while pushing docker image from artifact")
}
if err := d.pushRepoMetadata(repospec, r); err != nil {
if err := d.pushRepoMetadata(repospec, REPOSITORY_SPECFILE, r); err != nil {
return errors.Wrap(err, "while pushing repository metadata tree")
}
// Create a named snapshot and push it.
// It edits the metadata pointing at the repository files associated with the snapshot
// And copies the new files
id := time.Now().Format("20060102150405")
artifacts, snapshotRepoFile, err := r.Snapshot(id, repoTemp)
if err != nil {
return errors.Wrap(err, "while creating snapshot")
}
if err := d.pushRepoMetadata(snapshotRepoFile, filepath.Base(snapshotRepoFile), r); err != nil {
return errors.Wrap(err, "while pushing repository snapshot metadata tree")
}
for _, a := range artifacts {
if err := d.pushImageFromArtifact(a, d.b, false); err != nil {
return errors.Wrap(err, "error met while pushing docker image from artifact")
}
}
bus.Manager.Publish(bus.EventRepositoryPostBuild, struct {
Repo LuetSystemRepository
Path string

View File

@@ -121,6 +121,13 @@ func (g *localRepositoryGenerator) Generate(r *LuetSystemRepository, dst string,
return errors.Wrap(err, "failed adding Metadata file to repository")
}
// Create named snapshot.
// It edits the metadata pointing at the repository files associated with the snapshot
// And copies the new files
if _, _, err := r.Snapshot(time.Now().Format("20060102150405"), dst); err != nil {
return errors.Wrap(err, "while creating snapshot")
}
bus.Manager.Publish(bus.EventRepositoryPostBuild, struct {
Repo LuetSystemRepository
Path string

View File

@@ -218,6 +218,124 @@ urls:
Expect(err).To(HaveOccurred()) // should throw error
})
It("Generates snapshots", func() {
tmpdir, err := ioutil.TempDir("", "tree")
Expect(err).ToNot(HaveOccurred())
defer os.RemoveAll(tmpdir) // clean up
generalRecipe := tree.NewCompilerRecipe(pkg.NewInMemoryDatabase(false))
err = generalRecipe.Load("../../tests/fixtures/buildable")
Expect(err).ToNot(HaveOccurred())
generalRecipe2 := tree.NewCompilerRecipe(pkg.NewInMemoryDatabase(false))
err = generalRecipe2.Load("../../tests/fixtures/finalizers")
Expect(err).ToNot(HaveOccurred())
Expect(len(generalRecipe2.GetDatabase().GetPackages())).To(Equal(1))
Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(3))
compiler2 := compiler.NewLuetCompiler(backend.NewSimpleDockerBackend(ctx), generalRecipe2.GetDatabase(), options.WithContext(ctx))
spec2, err := compiler2.FromPackage(&pkg.DefaultPackage{Name: "alpine", Category: "seed", Version: "1.0"})
Expect(err).ToNot(HaveOccurred())
compiler := compiler.NewLuetCompiler(backend.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase(), options.WithContext(ctx))
spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"})
Expect(err).ToNot(HaveOccurred())
Expect(spec.GetPackage().GetPath()).ToNot(Equal(""))
Expect(spec2.GetPackage().GetPath()).ToNot(Equal(""))
tmpdir, err = ioutil.TempDir("", "tree")
Expect(err).ToNot(HaveOccurred())
defer os.RemoveAll(tmpdir) // clean up
Expect(spec.BuildSteps()).To(Equal([]string{"echo artifact5 > /test5", "echo artifact6 > /test6", "chmod +x generate.sh", "./generate.sh"}))
Expect(spec.GetPreBuildSteps()).To(Equal([]string{"echo foo > /test", "echo bar > /test2"}))
spec.SetOutputPath(tmpdir)
spec2.SetOutputPath(tmpdir)
artifact, err := compiler.Compile(false, spec)
Expect(err).ToNot(HaveOccurred())
Expect(fileHelper.Exists(artifact.Path)).To(BeTrue())
Expect(helpers.Untar(artifact.Path, tmpdir, false)).ToNot(HaveOccurred())
artifact2, err := compiler2.Compile(false, spec2)
Expect(err).ToNot(HaveOccurred())
Expect(fileHelper.Exists(artifact2.Path)).To(BeTrue())
Expect(helpers.Untar(artifact2.Path, tmpdir, false)).ToNot(HaveOccurred())
Expect(fileHelper.Exists(spec.Rel("test5"))).To(BeTrue())
Expect(fileHelper.Exists(spec.Rel("test6"))).To(BeTrue())
content1, err := fileHelper.Read(spec.Rel("test5"))
Expect(err).ToNot(HaveOccurred())
content2, err := fileHelper.Read(spec.Rel("test6"))
Expect(err).ToNot(HaveOccurred())
Expect(content1).To(Equal("artifact5\n"))
Expect(content2).To(Equal("artifact6\n"))
// will contain both
Expect(fileHelper.Exists(spec.Rel("b-test-1.0.package.tar"))).To(BeTrue())
Expect(fileHelper.Exists(spec.Rel("b-test-1.0.metadata.yaml"))).To(BeTrue())
Expect(fileHelper.Exists(spec2.Rel("alpine-seed-1.0.package.tar"))).To(BeTrue())
Expect(fileHelper.Exists(spec2.Rel("alpine-seed-1.0.metadata.yaml"))).To(BeTrue())
repo, err := GenerateRepository(
WithName("test"),
WithDescription("description"),
WithType("disk"),
WithUrls(tmpdir),
WithPriority(1),
WithSource(tmpdir),
FromMetadata(true), // Enabling from metadata makes the package visible
WithTree("../../tests/fixtures/buildable"),
WithContext(ctx),
WithDatabase(pkg.NewInMemoryDatabase(false)),
)
Expect(err).ToNot(HaveOccurred())
Expect(repo.GetName()).To(Equal("test"))
Expect(fileHelper.Exists(spec.Rel(REPOSITORY_SPECFILE))).ToNot(BeTrue())
Expect(fileHelper.Exists(spec.Rel(TREE_TARBALL + ".gz"))).ToNot(BeTrue())
Expect(fileHelper.Exists(spec.Rel(REPOSITORY_METAFILE + ".tar"))).ToNot(BeTrue())
err = repo.Write(ctx, tmpdir, false, true)
Expect(err).ToNot(HaveOccurred())
Expect(fileHelper.Exists(spec.Rel(REPOSITORY_SPECFILE))).To(BeTrue())
Expect(fileHelper.Exists(spec.Rel(TREE_TARBALL + ".gz"))).To(BeTrue())
Expect(fileHelper.Exists(spec.Rel(REPOSITORY_METAFILE + ".tar"))).To(BeTrue())
artifacts, index, err := repo.Snapshot("foo", tmpdir)
Expect(err).ToNot(HaveOccurred())
Expect(len(artifacts)).To(Equal(3))
Expect(index).To(ContainSubstring("foo-repository.yaml"))
r := &LuetSystemRepository{}
r, err = r.ReadSpecFile(index)
Expect(err).ToNot(HaveOccurred())
Expect(err).ToNot(HaveOccurred())
Expect(len(r.RepositoryFiles)).To(Equal(3))
for k, v := range r.RepositoryFiles {
_, err := os.Stat(filepath.Join(tmpdir, "foo-compilertree.tar.gz"))
Expect(err).ToNot(HaveOccurred())
switch k {
case REPOFILE_COMPILER_TREE_KEY:
Expect(v.FileName).To(Equal("foo-compilertree.tar.gz"))
case REPOFILE_META_KEY:
Expect(v.FileName).To(Equal("foo-repository.meta.yaml.tar"))
case REPOFILE_TREE_KEY:
Expect(v.FileName).To(Equal("foo-tree.tar.gz"))
}
}
})
It("Generate repository metadata of files referenced in a tree and from packages", func() {
tmpdir, err := ioutil.TempDir("", "tree")