Define context for scoped operation across core types

It holds necessary state plus additional information relative to the
context which we are being run to (e.g. if we are in a terminal or not).
Besides in the future we can use it also as a contextual logger to
provide more smart logging capabilities.

This also replace the general global configuration instance that
previously was share between the core components.
This commit is contained in:
Ettore Di Giacinto 2021-10-21 00:13:02 +02:00
parent b9895c9e05
commit a1c669d3ae
89 changed files with 1774 additions and 1849 deletions

View File

@ -21,8 +21,8 @@ import (
b64 "encoding/base64" b64 "encoding/base64"
"github.com/mudler/luet/cmd/util"
"github.com/mudler/luet/pkg/box" "github.com/mudler/luet/pkg/box"
. "github.com/mudler/luet/pkg/logger"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
@ -54,18 +54,18 @@ func NewBoxExecCommand() *cobra.Command {
args = ss args = ss
} }
Info("Executing", args, "in", rootfs) util.DefaultContext.Info("Executing", args, "in", rootfs)
b := box.NewBox(entrypoint, args, mounts, envs, rootfs, stdin, stdout, stderr) b := box.NewBox(entrypoint, args, mounts, envs, rootfs, stdin, stdout, stderr)
err := b.Run() err := b.Run()
if err != nil { if err != nil {
Fatal(err) util.DefaultContext.Fatal(err)
} }
}, },
} }
path, err := os.Getwd() path, err := os.Getwd()
if err != nil { if err != nil {
Fatal(err) util.DefaultContext.Fatal(err)
} }
ans.Flags().String("rootfs", path, "Rootfs path") ans.Flags().String("rootfs", path, "Rootfs path")
ans.Flags().Bool("stdin", false, "Attach to stdin") ans.Flags().Bool("stdin", false, "Attach to stdin")

View File

@ -29,8 +29,6 @@ import (
"github.com/mudler/luet/pkg/compiler/types/compression" "github.com/mudler/luet/pkg/compiler/types/compression"
"github.com/mudler/luet/pkg/compiler/types/options" "github.com/mudler/luet/pkg/compiler/types/options"
. "github.com/mudler/luet/pkg/config"
. "github.com/mudler/luet/pkg/logger"
pkg "github.com/mudler/luet/pkg/package" pkg "github.com/mudler/luet/pkg/package"
"github.com/mudler/luet/pkg/solver" "github.com/mudler/luet/pkg/solver"
tree "github.com/mudler/luet/pkg/tree" tree "github.com/mudler/luet/pkg/tree"
@ -94,7 +92,7 @@ Build packages specifying multiple definition trees:
treePaths := viper.GetStringSlice("tree") treePaths := viper.GetStringSlice("tree")
dst := viper.GetString("destination") dst := viper.GetString("destination")
concurrency := LuetCfg.GetGeneral().Concurrency concurrency := util.DefaultContext.Config.GetGeneral().Concurrency
backendType := viper.GetString("backend") backendType := viper.GetString("backend")
privileged := viper.GetBool("privileged") privileged := viper.GetBool("privileged")
revdeps := viper.GetBool("revdeps") revdeps := viper.GetBool("revdeps")
@ -117,7 +115,7 @@ Build packages specifying multiple definition trees:
out, _ := cmd.Flags().GetString("output") out, _ := cmd.Flags().GetString("output")
if out != "terminal" { if out != "terminal" {
LuetCfg.GetLogging().SetLogLevel("error") util.DefaultContext.Config.GetLogging().SetLogLevel("error")
} }
pretend, _ := cmd.Flags().GetBool("pretend") pretend, _ := cmd.Flags().GetBool("pretend")
fromRepo, _ := cmd.Flags().GetBool("from-repositories") fromRepo, _ := cmd.Flags().GetBool("from-repositories")
@ -125,7 +123,7 @@ Build packages specifying multiple definition trees:
compilerSpecs := compilerspec.NewLuetCompilationspecs() compilerSpecs := compilerspec.NewLuetCompilationspecs()
var db pkg.PackageDatabase var db pkg.PackageDatabase
compilerBackend, err := compiler.NewBackend(backendType) compilerBackend, err := compiler.NewBackend(util.DefaultContext, backendType)
helpers.CheckErr(err) helpers.CheckErr(err)
db = pkg.NewInMemoryDatabase(false) db = pkg.NewInMemoryDatabase(false)
@ -134,24 +132,24 @@ Build packages specifying multiple definition trees:
generalRecipe := tree.NewCompilerRecipe(db) generalRecipe := tree.NewCompilerRecipe(db)
if fromRepo { if fromRepo {
if err := installer.LoadBuildTree(generalRecipe, db, LuetCfg); err != nil { if err := installer.LoadBuildTree(generalRecipe, db, util.DefaultContext); err != nil {
Warning("errors while loading trees from repositories", err.Error()) util.DefaultContext.Warning("errors while loading trees from repositories", err.Error())
} }
} }
for _, src := range treePaths { for _, src := range treePaths {
Info("Loading tree", src) util.DefaultContext.Info("Loading tree", src)
helpers.CheckErr(generalRecipe.Load(src)) helpers.CheckErr(generalRecipe.Load(src))
} }
Info("Building in", dst) util.DefaultContext.Info("Building in", dst)
opts := util.SetSolverConfig() opts := util.SetSolverConfig(util.DefaultContext)
pullRepo, _ := cmd.Flags().GetStringArray("pull-repository") pullRepo, _ := cmd.Flags().GetStringArray("pull-repository")
LuetCfg.GetGeneral().ShowBuildOutput = viper.GetBool("general.show_build_output") util.DefaultContext.Config.GetGeneral().ShowBuildOutput = viper.GetBool("general.show_build_output")
Debug("Solver", opts.CompactString()) util.DefaultContext.Debug("Solver", opts.CompactString())
opts.Options = solver.Options{Type: solver.SingleCoreSimple, Concurrency: concurrency} opts.Options = solver.Options{Type: solver.SingleCoreSimple, Concurrency: concurrency}
@ -163,13 +161,14 @@ Build packages specifying multiple definition trees:
options.WithPullRepositories(pullRepo), options.WithPullRepositories(pullRepo),
options.WithPushRepository(imageRepository), options.WithPushRepository(imageRepository),
options.Rebuild(rebuild), options.Rebuild(rebuild),
options.WithTemplateFolder(util.TemplateFolders(fromRepo, treePaths)), options.WithTemplateFolder(util.TemplateFolders(util.DefaultContext, fromRepo, treePaths)),
options.WithSolverOptions(*opts), options.WithSolverOptions(*opts),
options.Wait(wait), options.Wait(wait),
options.OnlyTarget(onlyTarget), options.OnlyTarget(onlyTarget),
options.PullFirst(pull), options.PullFirst(pull),
options.KeepImg(keepImages), options.KeepImg(keepImages),
options.OnlyDeps(onlydeps), options.OnlyDeps(onlydeps),
options.WithContext(util.DefaultContext),
options.BackendArgs(backendArgs), options.BackendArgs(backendArgs),
options.Concurrency(concurrency), options.Concurrency(concurrency),
options.WithCompressionType(compression.Implementation(compressionType)), options.WithCompressionType(compression.Implementation(compressionType)),
@ -178,10 +177,10 @@ Build packages specifying multiple definition trees:
if full { if full {
specs, err := luetCompiler.FromDatabase(generalRecipe.GetDatabase(), true, dst) specs, err := luetCompiler.FromDatabase(generalRecipe.GetDatabase(), true, dst)
if err != nil { if err != nil {
Fatal(err.Error()) util.DefaultContext.Fatal(err.Error())
} }
for _, spec := range specs { for _, spec := range specs {
Info(":package: Selecting ", spec.GetPackage().GetName(), spec.GetPackage().GetVersion()) util.DefaultContext.Info(":package: Selecting ", spec.GetPackage().GetName(), spec.GetPackage().GetVersion())
compilerSpecs.Add(spec) compilerSpecs.Add(spec)
} }
@ -189,12 +188,12 @@ Build packages specifying multiple definition trees:
for _, a := range args { for _, a := range args {
pack, err := helpers.ParsePackageStr(a) pack, err := helpers.ParsePackageStr(a)
if err != nil { if err != nil {
Fatal("Invalid package string ", a, ": ", err.Error()) util.DefaultContext.Fatal("Invalid package string ", a, ": ", err.Error())
} }
spec, err := luetCompiler.FromPackage(pack) spec, err := luetCompiler.FromPackage(pack)
if err != nil { if err != nil {
Fatal("Error: " + err.Error()) util.DefaultContext.Fatal("Error: " + err.Error())
} }
spec.SetOutputPath(dst) spec.SetOutputPath(dst)
@ -206,9 +205,9 @@ Build packages specifying multiple definition trees:
for _, p := range w { for _, p := range w {
spec, err := luetCompiler.FromPackage(p) spec, err := luetCompiler.FromPackage(p)
if err != nil { if err != nil {
Fatal("Error: " + err.Error()) util.DefaultContext.Fatal("Error: " + err.Error())
} }
Info(":package: Selecting ", p.GetName(), p.GetVersion()) util.DefaultContext.Info(":package: Selecting ", p.GetName(), p.GetVersion())
spec.SetOutputPath(dst) spec.SetOutputPath(dst)
compilerSpecs.Add(spec) compilerSpecs.Add(spec)
} }
@ -267,7 +266,7 @@ Build packages specifying multiple definition trees:
fmt.Println(string(j2)) fmt.Println(string(j2))
case "terminal": case "terminal":
for _, p := range results.Packages { for _, p := range results.Packages {
Info(p.String()) util.DefaultContext.Info(p.String())
} }
} }
} else { } else {
@ -276,12 +275,12 @@ Build packages specifying multiple definition trees:
} }
if len(errs) != 0 { if len(errs) != 0 {
for _, e := range errs { for _, e := range errs {
Error("Error: " + e.Error()) util.DefaultContext.Error("Error: " + e.Error())
} }
Fatal("Bailing out") util.DefaultContext.Fatal("Bailing out")
} }
for _, a := range artifact { for _, a := range artifact {
Info("Artifact generated:", a.Path) util.DefaultContext.Info("Artifact generated:", a.Path)
} }
}, },
} }
@ -289,7 +288,7 @@ Build packages specifying multiple definition trees:
func init() { func init() {
path, err := os.Getwd() path, err := os.Getwd()
if err != nil { if err != nil {
Fatal(err) util.DefaultContext.Fatal(err)
} }
buildCmd.Flags().StringSliceP("tree", "t", []string{path}, "Path of the tree to use.") buildCmd.Flags().StringSliceP("tree", "t", []string{path}, "Path of the tree to use.")
@ -316,7 +315,7 @@ func init() {
buildCmd.Flags().Float32("solver-discount", 1.0, "Solver discount rate") buildCmd.Flags().Float32("solver-discount", 1.0, "Solver discount rate")
buildCmd.Flags().Int("solver-attempts", 9000, "Solver maximum attempts") buildCmd.Flags().Int("solver-attempts", 9000, "Solver maximum attempts")
buildCmd.Flags().Bool("solver-concurrent", false, "Use concurrent solver (experimental)") buildCmd.Flags().Bool("solver-concurrent", false, "Use concurrent solver (experimental)")
buildCmd.Flags().Bool("live-output", LuetCfg.GetGeneral().ShowBuildOutput, "Enable live output of the build phase.") buildCmd.Flags().Bool("live-output", util.DefaultContext.Config.GetGeneral().ShowBuildOutput, "Enable live output of the build phase.")
buildCmd.Flags().Bool("from-repositories", false, "Consume the user-defined repositories to pull specfiles from") buildCmd.Flags().Bool("from-repositories", false, "Consume the user-defined repositories to pull specfiles from")
buildCmd.Flags().Bool("rebuild", false, "To combine with --pull. Allows to rebuild the target package even if an image is available, against a local values file") buildCmd.Flags().Bool("rebuild", false, "To combine with --pull. Allows to rebuild the target package even if an image is available, against a local values file")
buildCmd.Flags().Bool("pretend", false, "Just print what packages will be compiled") buildCmd.Flags().Bool("pretend", false, "Just print what packages will be compiled")

View File

@ -21,9 +21,7 @@ import (
"path/filepath" "path/filepath"
"github.com/mudler/luet/cmd/util" "github.com/mudler/luet/cmd/util"
. "github.com/mudler/luet/pkg/config"
fileHelper "github.com/mudler/luet/pkg/helpers/file" fileHelper "github.com/mudler/luet/pkg/helpers/file"
. "github.com/mudler/luet/pkg/logger"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
@ -37,13 +35,13 @@ var cleanupCmd = &cobra.Command{
}, },
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
var cleaned int = 0 var cleaned int = 0
util.SetSystemConfig() util.SetSystemConfig(util.DefaultContext)
// Check if cache dir exists // Check if cache dir exists
if fileHelper.Exists(LuetCfg.GetSystem().GetSystemPkgsCacheDirPath()) { if fileHelper.Exists(util.DefaultContext.Config.GetSystem().GetSystemPkgsCacheDirPath()) {
files, err := ioutil.ReadDir(LuetCfg.GetSystem().GetSystemPkgsCacheDirPath()) files, err := ioutil.ReadDir(util.DefaultContext.Config.GetSystem().GetSystemPkgsCacheDirPath())
if err != nil { if err != nil {
Fatal("Error on read cachedir ", err.Error()) util.DefaultContext.Fatal("Error on read cachedir ", err.Error())
} }
for _, file := range files { for _, file := range files {
@ -51,20 +49,20 @@ var cleanupCmd = &cobra.Command{
continue continue
} }
if LuetCfg.GetGeneral().Debug { if util.DefaultContext.Config.GetGeneral().Debug {
Info("Removing ", file.Name()) util.DefaultContext.Info("Removing ", file.Name())
} }
err := os.RemoveAll( err := os.RemoveAll(
filepath.Join(LuetCfg.GetSystem().GetSystemPkgsCacheDirPath(), file.Name())) filepath.Join(util.DefaultContext.Config.GetSystem().GetSystemPkgsCacheDirPath(), file.Name()))
if err != nil { if err != nil {
Fatal("Error on removing", file.Name()) util.DefaultContext.Fatal("Error on removing", file.Name())
} }
cleaned++ cleaned++
} }
} }
Info("Cleaned: ", cleaned, "packages.") util.DefaultContext.Info("Cleaned: ", cleaned, "packages.")
}, },
} }

View File

@ -18,8 +18,7 @@ package cmd
import ( import (
"fmt" "fmt"
config "github.com/mudler/luet/pkg/config" "github.com/mudler/luet/cmd/util"
. "github.com/mudler/luet/pkg/logger"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
@ -30,9 +29,9 @@ var configCmd = &cobra.Command{
Long: `Show luet configuration`, Long: `Show luet configuration`,
Aliases: []string{"c"}, Aliases: []string{"c"},
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
data, err := config.LuetCfg.YAML() data, err := util.DefaultContext.Config.YAML()
if err != nil { if err != nil {
Fatal(err.Error()) util.DefaultContext.Fatal(err.Error())
} }
fmt.Println(string(data)) fmt.Println(string(data))

View File

@ -19,9 +19,9 @@ import (
"path/filepath" "path/filepath"
helpers "github.com/mudler/luet/cmd/helpers" helpers "github.com/mudler/luet/cmd/helpers"
"github.com/mudler/luet/cmd/util"
"github.com/mudler/luet/pkg/compiler" "github.com/mudler/luet/pkg/compiler"
"github.com/mudler/luet/pkg/compiler/types/compression" "github.com/mudler/luet/pkg/compiler/types/compression"
. "github.com/mudler/luet/pkg/config"
installer "github.com/mudler/luet/pkg/installer" installer "github.com/mudler/luet/pkg/installer"
// . "github.com/mudler/luet/pkg/logger" // . "github.com/mudler/luet/pkg/logger"
@ -96,7 +96,7 @@ Create a repository from the metadata description defined in the luet.yaml confi
treeFile := installer.NewDefaultTreeRepositoryFile() treeFile := installer.NewDefaultTreeRepositoryFile()
metaFile := installer.NewDefaultMetaRepositoryFile() metaFile := installer.NewDefaultMetaRepositoryFile()
compilerBackend, err := compiler.NewBackend(backendType) compilerBackend, err := compiler.NewBackend(util.DefaultContext, backendType)
helpers.CheckErr(err) helpers.CheckErr(err)
force := viper.GetBool("force-push") force := viper.GetBool("force-push")
imagePush := viper.GetBool("push-images") imagePush := viper.GetBool("push-images")
@ -106,16 +106,16 @@ Create a repository from the metadata description defined in the luet.yaml confi
installer.WithPushImages(imagePush), installer.WithPushImages(imagePush),
installer.WithForce(force), installer.WithForce(force),
installer.FromRepository(fromRepo), installer.FromRepository(fromRepo),
installer.WithConfig(LuetCfg),
installer.WithImagePrefix(dst), installer.WithImagePrefix(dst),
installer.WithDatabase(pkg.NewInMemoryDatabase(false)), installer.WithDatabase(pkg.NewInMemoryDatabase(false)),
installer.WithCompilerBackend(compilerBackend), installer.WithCompilerBackend(compilerBackend),
installer.FromMetadata(viper.GetBool("from-metadata")), installer.FromMetadata(viper.GetBool("from-metadata")),
installer.WithContext(util.DefaultContext),
} }
if source_repo != "" { if source_repo != "" {
// Search for system repository // Search for system repository
lrepo, err := LuetCfg.GetSystemRepository(source_repo) lrepo, err := util.DefaultContext.Config.GetSystemRepository(source_repo)
helpers.CheckErr(err) helpers.CheckErr(err)
if len(treePaths) <= 0 { if len(treePaths) <= 0 {
@ -167,7 +167,7 @@ Create a repository from the metadata description defined in the luet.yaml confi
repo.SetRepositoryFile(installer.REPOFILE_TREE_KEY, treeFile) repo.SetRepositoryFile(installer.REPOFILE_TREE_KEY, treeFile)
repo.SetRepositoryFile(installer.REPOFILE_META_KEY, metaFile) repo.SetRepositoryFile(installer.REPOFILE_META_KEY, metaFile)
err = repo.Write(dst, reset, true) err = repo.Write(util.DefaultContext, dst, reset, true)
helpers.CheckErr(err) helpers.CheckErr(err)
}, },

View File

@ -21,11 +21,8 @@ import (
"github.com/mudler/luet/cmd/util" "github.com/mudler/luet/cmd/util"
artifact "github.com/mudler/luet/pkg/api/core/types/artifact" artifact "github.com/mudler/luet/pkg/api/core/types/artifact"
. "github.com/mudler/luet/pkg/logger"
pkg "github.com/mudler/luet/pkg/package" pkg "github.com/mudler/luet/pkg/package"
. "github.com/mudler/luet/pkg/config"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
@ -50,35 +47,35 @@ For reference, inspect a "metadata.yaml" file generated while running "luet buil
}, },
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
util.SetSystemConfig() util.SetSystemConfig(util.DefaultContext)
systemDB := LuetCfg.GetSystemDB() systemDB := util.DefaultContext.Config.GetSystemDB()
for _, a := range args { for _, a := range args {
dat, err := ioutil.ReadFile(a) dat, err := ioutil.ReadFile(a)
if err != nil { if err != nil {
Fatal("Failed reading ", a, ": ", err.Error()) util.DefaultContext.Fatal("Failed reading ", a, ": ", err.Error())
} }
art, err := artifact.NewPackageArtifactFromYaml(dat) art, err := artifact.NewPackageArtifactFromYaml(dat)
if err != nil { if err != nil {
Fatal("Failed reading yaml ", a, ": ", err.Error()) util.DefaultContext.Fatal("Failed reading yaml ", a, ": ", err.Error())
} }
files := art.Files files := art.Files
// Check if the package is already present // Check if the package is already present
if p, err := systemDB.FindPackage(art.CompileSpec.GetPackage()); err == nil && p.GetName() != "" { if p, err := systemDB.FindPackage(art.CompileSpec.GetPackage()); err == nil && p.GetName() != "" {
Fatal("Package", art.CompileSpec.GetPackage().HumanReadableString(), util.DefaultContext.Fatal("Package", art.CompileSpec.GetPackage().HumanReadableString(),
" already present.") " already present.")
} }
if _, err := systemDB.CreatePackage(art.CompileSpec.GetPackage()); err != nil { if _, err := systemDB.CreatePackage(art.CompileSpec.GetPackage()); err != nil {
Fatal("Failed to create ", a, ": ", err.Error()) util.DefaultContext.Fatal("Failed to create ", a, ": ", err.Error())
} }
if err := systemDB.SetPackageFiles(&pkg.PackageFile{PackageFingerprint: art.CompileSpec.GetPackage().GetFingerPrint(), Files: files}); err != nil { if err := systemDB.SetPackageFiles(&pkg.PackageFile{PackageFingerprint: art.CompileSpec.GetPackage().GetFingerPrint(), Files: files}); err != nil {
Fatal("Failed setting package files for ", a, ": ", err.Error()) util.DefaultContext.Fatal("Failed setting package files for ", a, ": ", err.Error())
} }
Info(art.CompileSpec.GetPackage().HumanReadableString(), " created") util.DefaultContext.Info(art.CompileSpec.GetPackage().HumanReadableString(), " created")
} }
}, },

View File

@ -22,8 +22,6 @@ import (
"github.com/mudler/luet/cmd/util" "github.com/mudler/luet/cmd/util"
"gopkg.in/yaml.v2" "gopkg.in/yaml.v2"
. "github.com/mudler/luet/pkg/config"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
@ -43,9 +41,9 @@ To return also files:
}, },
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
showFiles, _ := cmd.Flags().GetBool("files") showFiles, _ := cmd.Flags().GetBool("files")
util.SetSystemConfig() util.SetSystemConfig(util.DefaultContext)
systemDB := LuetCfg.GetSystemDB() systemDB := util.DefaultContext.Config.GetSystemDB()
for _, a := range args { for _, a := range args {
pack, err := helpers.ParsePackageStr(a) pack, err := helpers.ParsePackageStr(a)

View File

@ -16,11 +16,8 @@
package cmd_database package cmd_database
import ( import (
. "github.com/mudler/luet/pkg/logger"
helpers "github.com/mudler/luet/cmd/helpers" helpers "github.com/mudler/luet/cmd/helpers"
"github.com/mudler/luet/cmd/util" "github.com/mudler/luet/cmd/util"
. "github.com/mudler/luet/pkg/config"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
@ -40,22 +37,22 @@ This commands takes multiple packages as arguments and prunes their entries from
util.BindSystemFlags(cmd) util.BindSystemFlags(cmd)
}, },
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
util.SetSystemConfig() util.SetSystemConfig(util.DefaultContext)
systemDB := LuetCfg.GetSystemDB() systemDB := util.DefaultContext.Config.GetSystemDB()
for _, a := range args { for _, a := range args {
pack, err := helpers.ParsePackageStr(a) pack, err := helpers.ParsePackageStr(a)
if err != nil { if err != nil {
Fatal("Invalid package string ", a, ": ", err.Error()) util.DefaultContext.Fatal("Invalid package string ", a, ": ", err.Error())
} }
if err := systemDB.RemovePackage(pack); err != nil { if err := systemDB.RemovePackage(pack); err != nil {
Fatal("Failed removing ", a, ": ", err.Error()) util.DefaultContext.Fatal("Failed removing ", a, ": ", err.Error())
} }
if err := systemDB.RemovePackageFiles(pack); err != nil { if err := systemDB.RemovePackageFiles(pack); err != nil {
Fatal("Failed removing files for ", a, ": ", err.Error()) util.DefaultContext.Fatal("Failed removing files for ", a, ": ", err.Error())
} }
} }

View File

@ -20,8 +20,8 @@ import (
b64 "encoding/base64" b64 "encoding/base64"
"github.com/mudler/luet/cmd/util"
"github.com/mudler/luet/pkg/box" "github.com/mudler/luet/pkg/box"
. "github.com/mudler/luet/pkg/logger"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
@ -55,12 +55,12 @@ var execCmd = &cobra.Command{
args = ss args = ss
} }
Info("Executing", args, "in", rootfs) util.DefaultContext.Info("Executing", args, "in", rootfs)
b := box.NewBox(entrypoint, args, mounts, envs, rootfs, stdin, stdout, stderr) b := box.NewBox(entrypoint, args, mounts, envs, rootfs, stdin, stdout, stderr)
err := b.Exec() err := b.Exec()
if err != nil { if err != nil {
Fatal(errors.Wrap(err, fmt.Sprintf("entrypoint: %s rootfs: %s", entrypoint, rootfs))) util.DefaultContext.Fatal(errors.Wrap(err, fmt.Sprintf("entrypoint: %s rootfs: %s", entrypoint, rootfs)))
} }
}, },
} }
@ -68,7 +68,7 @@ var execCmd = &cobra.Command{
func init() { func init() {
path, err := os.Getwd() path, err := os.Getwd()
if err != nil { if err != nil {
Fatal(err) util.DefaultContext.Fatal(err)
} }
execCmd.Hidden = true execCmd.Hidden = true
execCmd.Flags().String("rootfs", path, "Rootfs path") execCmd.Flags().String("rootfs", path, "Rootfs path")

View File

@ -22,9 +22,8 @@ import (
"regexp" "regexp"
"strings" "strings"
. "github.com/mudler/luet/pkg/logger"
_gentoo "github.com/Sabayon/pkgs-checker/pkg/gentoo" _gentoo "github.com/Sabayon/pkgs-checker/pkg/gentoo"
"github.com/mudler/luet/cmd/util"
pkg "github.com/mudler/luet/pkg/package" pkg "github.com/mudler/luet/pkg/package"
) )
@ -126,6 +125,6 @@ func ParsePackageStr(p string) (*pkg.DefaultPackage, error) {
func CheckErr(err error) { func CheckErr(err error) {
if err != nil { if err != nil {
Fatal(err) util.DefaultContext.Fatal(err)
} }
} }

View File

@ -18,14 +18,11 @@ package cmd_helpers_test
import ( import (
"testing" "testing"
. "github.com/mudler/luet/cmd/util"
. "github.com/onsi/ginkgo" . "github.com/onsi/ginkgo"
. "github.com/onsi/gomega" . "github.com/onsi/gomega"
) )
func TestSolver(t *testing.T) { func TestSolver(t *testing.T) {
RegisterFailHandler(Fail) RegisterFailHandler(Fail)
LoadConfig()
RunSpecs(t, "CLI helpers test Suite") RunSpecs(t, "CLI helpers test Suite")
} }

View File

@ -15,13 +15,12 @@
package cmd package cmd
import ( import (
"github.com/mudler/luet/pkg/api/core/types"
installer "github.com/mudler/luet/pkg/installer" installer "github.com/mudler/luet/pkg/installer"
"github.com/mudler/luet/pkg/solver" "github.com/mudler/luet/pkg/solver"
helpers "github.com/mudler/luet/cmd/helpers" helpers "github.com/mudler/luet/cmd/helpers"
"github.com/mudler/luet/cmd/util" "github.com/mudler/luet/cmd/util"
. "github.com/mudler/luet/pkg/config"
. "github.com/mudler/luet/pkg/logger"
pkg "github.com/mudler/luet/pkg/package" pkg "github.com/mudler/luet/pkg/package"
"github.com/spf13/cobra" "github.com/spf13/cobra"
@ -62,7 +61,7 @@ To force install a package:
for _, a := range args { for _, a := range args {
pack, err := helpers.ParsePackageStr(a) pack, err := helpers.ParsePackageStr(a)
if err != nil { if err != nil {
Fatal("Invalid package string ", a, ": ", err.Error()) util.DefaultContext.Fatal("Invalid package string ", a, ": ", err.Error())
} }
toInstall = append(toInstall, pack) toInstall = append(toInstall, pack)
} }
@ -75,25 +74,25 @@ To force install a package:
finalizerEnvs, _ := cmd.Flags().GetStringArray("finalizer-env") finalizerEnvs, _ := cmd.Flags().GetStringArray("finalizer-env")
relax, _ := cmd.Flags().GetBool("relax") relax, _ := cmd.Flags().GetBool("relax")
util.SetSystemConfig() util.SetSystemConfig(util.DefaultContext)
util.SetSolverConfig() util.SetSolverConfig(util.DefaultContext)
LuetCfg.GetSolverOptions().Implementation = solver.SingleCoreSimple util.DefaultContext.Config.GetSolverOptions().Implementation = solver.SingleCoreSimple
Debug("Solver", LuetCfg.GetSolverOptions().CompactString()) util.DefaultContext.Debug("Solver", util.DefaultContext.Config.GetSolverOptions().CompactString())
// Load config protect configs // Load config protect configs
installer.LoadConfigProtectConfs(LuetCfg) util.DefaultContext.Config.LoadConfigProtect(util.DefaultContext)
// Load finalizer runtime environments // Load finalizer runtime environments
err := util.SetCliFinalizerEnvs(finalizerEnvs) err := util.SetCliFinalizerEnvs(util.DefaultContext, finalizerEnvs)
if err != nil { if err != nil {
Fatal(err.Error()) util.DefaultContext.Fatal(err.Error())
} }
inst := installer.NewLuetInstaller(installer.LuetInstallerOptions{ inst := installer.NewLuetInstaller(installer.LuetInstallerOptions{
Concurrency: LuetCfg.GetGeneral().Concurrency, Concurrency: util.DefaultContext.Config.GetGeneral().Concurrency,
SolverOptions: *LuetCfg.GetSolverOptions(), SolverOptions: *util.DefaultContext.Config.GetSolverOptions(),
NoDeps: nodeps, NoDeps: nodeps,
Force: force, Force: force,
OnlyDeps: onlydeps, OnlyDeps: onlydeps,
@ -101,13 +100,14 @@ To force install a package:
DownloadOnly: downloadOnly, DownloadOnly: downloadOnly,
Ask: !yes, Ask: !yes,
Relaxed: relax, Relaxed: relax,
PackageRepositories: LuetCfg.SystemRepositories, PackageRepositories: util.DefaultContext.Config.SystemRepositories,
Context: util.DefaultContext,
}) })
system := &installer.System{Database: LuetCfg.GetSystemDB(), Target: LuetCfg.GetSystem().Rootfs} system := &installer.System{Database: util.DefaultContext.Config.GetSystemDB(), Target: util.DefaultContext.Config.GetSystem().Rootfs}
err = inst.Install(toInstall, system) err = inst.Install(toInstall, system)
if err != nil { if err != nil {
Fatal("Error: " + err.Error()) util.DefaultContext.Fatal("Error: " + err.Error())
} }
}, },
} }
@ -117,7 +117,7 @@ func init() {
installCmd.Flags().String("system-target", "", "System rootpath") installCmd.Flags().String("system-target", "", "System rootpath")
installCmd.Flags().String("system-engine", "", "System DB engine") installCmd.Flags().String("system-engine", "", "System DB engine")
installCmd.Flags().String("solver-type", "", "Solver strategy ( Defaults none, available: "+AvailableResolvers+" )") installCmd.Flags().String("solver-type", "", "Solver strategy ( Defaults none, available: "+types.AvailableResolvers+" )")
installCmd.Flags().Float32("solver-rate", 0.7, "Solver learning rate") installCmd.Flags().Float32("solver-rate", 0.7, "Solver learning rate")
installCmd.Flags().Float32("solver-discount", 1.0, "Solver discount rate") installCmd.Flags().Float32("solver-discount", 1.0, "Solver discount rate")
installCmd.Flags().Int("solver-attempts", 9000, "Solver maximum attempts") installCmd.Flags().Int("solver-attempts", 9000, "Solver maximum attempts")

View File

@ -20,11 +20,10 @@ import (
"time" "time"
helpers "github.com/mudler/luet/cmd/helpers" helpers "github.com/mudler/luet/cmd/helpers"
"github.com/mudler/luet/cmd/util"
"github.com/mudler/luet/pkg/api/core/types/artifact" "github.com/mudler/luet/pkg/api/core/types/artifact"
"github.com/mudler/luet/pkg/compiler/types/compression" "github.com/mudler/luet/pkg/compiler/types/compression"
compilerspec "github.com/mudler/luet/pkg/compiler/types/spec" compilerspec "github.com/mudler/luet/pkg/compiler/types/spec"
. "github.com/mudler/luet/pkg/config"
. "github.com/mudler/luet/pkg/logger"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/viper" "github.com/spf13/viper"
@ -53,17 +52,17 @@ Afterwards, you can use the content generated and associate it with a tree and a
dst := viper.GetString("destination") dst := viper.GetString("destination")
compressionType := viper.GetString("compression") compressionType := viper.GetString("compression")
concurrency := LuetCfg.GetGeneral().Concurrency concurrency := util.DefaultContext.Config.GetGeneral().Concurrency
if len(args) != 1 { if len(args) != 1 {
Fatal("You must specify a package name") util.DefaultContext.Fatal("You must specify a package name")
} }
packageName := args[0] packageName := args[0]
p, err := helpers.ParsePackageStr(packageName) p, err := helpers.ParsePackageStr(packageName)
if err != nil { if err != nil {
Fatal("Invalid package string ", packageName, ": ", err.Error()) util.DefaultContext.Fatal("Invalid package string ", packageName, ": ", err.Error())
} }
spec := &compilerspec.LuetCompilationSpec{Package: p} spec := &compilerspec.LuetCompilationSpec{Package: p}
@ -71,18 +70,18 @@ Afterwards, you can use the content generated and associate it with a tree and a
a.CompressionType = compression.Implementation(compressionType) a.CompressionType = compression.Implementation(compressionType)
err = a.Compress(sourcePath, concurrency) err = a.Compress(sourcePath, concurrency)
if err != nil { if err != nil {
Fatal("failed compressing ", packageName, ": ", err.Error()) util.DefaultContext.Fatal("failed compressing ", packageName, ": ", err.Error())
} }
a.CompileSpec = spec a.CompileSpec = spec
filelist, err := a.FileList() filelist, err := a.FileList()
if err != nil { if err != nil {
Fatal("failed generating file list for ", packageName, ": ", err.Error()) util.DefaultContext.Fatal("failed generating file list for ", packageName, ": ", err.Error())
} }
a.Files = filelist a.Files = filelist
a.CompileSpec.GetPackage().SetBuildTimestamp(time.Now().String()) a.CompileSpec.GetPackage().SetBuildTimestamp(time.Now().String())
err = a.WriteYAML(dst) err = a.WriteYAML(dst)
if err != nil { if err != nil {
Fatal("failed writing metadata yaml file for ", packageName, ": ", err.Error()) util.DefaultContext.Fatal("failed writing metadata yaml file for ", packageName, ": ", err.Error())
} }
}, },
} }
@ -90,7 +89,7 @@ Afterwards, you can use the content generated and associate it with a tree and a
func init() { func init() {
path, err := os.Getwd() path, err := os.Getwd()
if err != nil { if err != nil {
Fatal(err) util.DefaultContext.Fatal(err)
} }
packCmd.Flags().String("source", path, "Source folder") packCmd.Flags().String("source", path, "Source folder")
packCmd.Flags().String("destination", path, "Destination folder") packCmd.Flags().String("destination", path, "Destination folder")

View File

@ -18,9 +18,6 @@ import (
"github.com/mudler/luet/cmd/util" "github.com/mudler/luet/cmd/util"
installer "github.com/mudler/luet/pkg/installer" installer "github.com/mudler/luet/pkg/installer"
. "github.com/mudler/luet/pkg/config"
. "github.com/mudler/luet/pkg/logger"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/viper" "github.com/spf13/viper"
) )
@ -39,23 +36,24 @@ var reclaimCmd = &cobra.Command{
It scans the target file system, and if finds a match with a package available in the repositories, it marks as installed in the system database. It scans the target file system, and if finds a match with a package available in the repositories, it marks as installed in the system database.
`, `,
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
util.SetSystemConfig() util.SetSystemConfig(util.DefaultContext)
force := viper.GetBool("force") force := viper.GetBool("force")
Debug("Solver", LuetCfg.GetSolverOptions().CompactString()) util.DefaultContext.Debug("Solver", util.DefaultContext.Config.GetSolverOptions().CompactString())
inst := installer.NewLuetInstaller(installer.LuetInstallerOptions{ inst := installer.NewLuetInstaller(installer.LuetInstallerOptions{
Concurrency: LuetCfg.GetGeneral().Concurrency, Concurrency: util.DefaultContext.Config.GetGeneral().Concurrency,
Force: force, Force: force,
PreserveSystemEssentialData: true, PreserveSystemEssentialData: true,
PackageRepositories: LuetCfg.SystemRepositories, PackageRepositories: util.DefaultContext.Config.SystemRepositories,
Context: util.DefaultContext,
}) })
system := &installer.System{Database: LuetCfg.GetSystemDB(), Target: LuetCfg.GetSystem().Rootfs} system := &installer.System{Database: util.DefaultContext.Config.GetSystemDB(), Target: util.DefaultContext.Config.GetSystem().Rootfs}
err := inst.Reclaim(system) err := inst.Reclaim(system)
if err != nil { if err != nil {
Fatal("Error: " + err.Error()) util.DefaultContext.Fatal("Error: " + err.Error())
} }
}, },
} }

View File

@ -15,13 +15,12 @@
package cmd package cmd
import ( import (
"github.com/mudler/luet/pkg/api/core/types"
installer "github.com/mudler/luet/pkg/installer" installer "github.com/mudler/luet/pkg/installer"
"github.com/mudler/luet/pkg/solver" "github.com/mudler/luet/pkg/solver"
helpers "github.com/mudler/luet/cmd/helpers" helpers "github.com/mudler/luet/cmd/helpers"
"github.com/mudler/luet/cmd/util" "github.com/mudler/luet/cmd/util"
. "github.com/mudler/luet/pkg/config"
. "github.com/mudler/luet/pkg/logger"
pkg "github.com/mudler/luet/pkg/package" pkg "github.com/mudler/luet/pkg/package"
"github.com/spf13/cobra" "github.com/spf13/cobra"
@ -54,42 +53,43 @@ var reinstallCmd = &cobra.Command{
downloadOnly, _ := cmd.Flags().GetBool("download-only") downloadOnly, _ := cmd.Flags().GetBool("download-only")
util.SetSystemConfig() util.SetSystemConfig(util.DefaultContext)
for _, a := range args { for _, a := range args {
pack, err := helpers.ParsePackageStr(a) pack, err := helpers.ParsePackageStr(a)
if err != nil { if err != nil {
Fatal("Invalid package string ", a, ": ", err.Error()) util.DefaultContext.Fatal("Invalid package string ", a, ": ", err.Error())
} }
toUninstall = append(toUninstall, pack) toUninstall = append(toUninstall, pack)
toAdd = append(toAdd, pack) toAdd = append(toAdd, pack)
} }
util.SetSolverConfig() util.SetSolverConfig(util.DefaultContext)
LuetCfg.GetSolverOptions().Implementation = solver.SingleCoreSimple util.DefaultContext.Config.GetSolverOptions().Implementation = solver.SingleCoreSimple
Debug("Solver", LuetCfg.GetSolverOptions().CompactString()) util.DefaultContext.Debug("Solver", util.DefaultContext.Config.GetSolverOptions().CompactString())
// Load config protect configs // Load config protect configs
installer.LoadConfigProtectConfs(LuetCfg) util.DefaultContext.Config.LoadConfigProtect(util.DefaultContext)
inst := installer.NewLuetInstaller(installer.LuetInstallerOptions{ inst := installer.NewLuetInstaller(installer.LuetInstallerOptions{
Concurrency: LuetCfg.GetGeneral().Concurrency, Concurrency: util.DefaultContext.Config.GetGeneral().Concurrency,
SolverOptions: *LuetCfg.GetSolverOptions(), SolverOptions: *util.DefaultContext.Config.GetSolverOptions(),
NoDeps: true, NoDeps: true,
Force: force, Force: force,
OnlyDeps: onlydeps, OnlyDeps: onlydeps,
PreserveSystemEssentialData: true, PreserveSystemEssentialData: true,
Ask: !yes, Ask: !yes,
DownloadOnly: downloadOnly, DownloadOnly: downloadOnly,
PackageRepositories: LuetCfg.SystemRepositories, Context: util.DefaultContext,
PackageRepositories: util.DefaultContext.Config.SystemRepositories,
}) })
system := &installer.System{Database: LuetCfg.GetSystemDB(), Target: LuetCfg.GetSystem().Rootfs} system := &installer.System{Database: util.DefaultContext.Config.GetSystemDB(), Target: util.DefaultContext.Config.GetSystem().Rootfs}
err := inst.Swap(toUninstall, toAdd, system) err := inst.Swap(toUninstall, toAdd, system)
if err != nil { if err != nil {
Fatal("Error: " + err.Error()) util.DefaultContext.Fatal("Error: " + err.Error())
} }
}, },
} }
@ -100,7 +100,7 @@ func init() {
reinstallCmd.Flags().String("system-target", "", "System rootpath") reinstallCmd.Flags().String("system-target", "", "System rootpath")
reinstallCmd.Flags().String("system-engine", "", "System DB engine") reinstallCmd.Flags().String("system-engine", "", "System DB engine")
reinstallCmd.Flags().String("solver-type", "", "Solver strategy ( Defaults none, available: "+AvailableResolvers+" )") reinstallCmd.Flags().String("solver-type", "", "Solver strategy ( Defaults none, available: "+types.AvailableResolvers+" )")
reinstallCmd.Flags().Float32("solver-rate", 0.7, "Solver learning rate") reinstallCmd.Flags().Float32("solver-rate", 0.7, "Solver learning rate")
reinstallCmd.Flags().Float32("solver-discount", 1.0, "Solver discount rate") reinstallCmd.Flags().Float32("solver-discount", 1.0, "Solver discount rate")
reinstallCmd.Flags().Int("solver-attempts", 9000, "Solver maximum attempts") reinstallCmd.Flags().Int("solver-attempts", 9000, "Solver maximum attempts")

View File

@ -15,13 +15,13 @@
package cmd package cmd
import ( import (
"github.com/mudler/luet/pkg/api/core/types"
installer "github.com/mudler/luet/pkg/installer" installer "github.com/mudler/luet/pkg/installer"
"github.com/mudler/luet/pkg/solver" "github.com/mudler/luet/pkg/solver"
helpers "github.com/mudler/luet/cmd/helpers" helpers "github.com/mudler/luet/cmd/helpers"
"github.com/mudler/luet/cmd/util" "github.com/mudler/luet/cmd/util"
. "github.com/mudler/luet/pkg/config"
. "github.com/mudler/luet/pkg/logger"
pkg "github.com/mudler/luet/pkg/package" pkg "github.com/mudler/luet/pkg/package"
"github.com/spf13/cobra" "github.com/spf13/cobra"
@ -57,12 +57,12 @@ var replaceCmd = &cobra.Command{
yes := viper.GetBool("yes") yes := viper.GetBool("yes")
downloadOnly, _ := cmd.Flags().GetBool("download-only") downloadOnly, _ := cmd.Flags().GetBool("download-only")
util.SetSystemConfig() util.SetSystemConfig(util.DefaultContext)
util.SetSolverConfig() util.SetSolverConfig(util.DefaultContext)
for _, a := range args { for _, a := range args {
pack, err := helpers.ParsePackageStr(a) pack, err := helpers.ParsePackageStr(a)
if err != nil { if err != nil {
Fatal("Invalid package string ", a, ": ", err.Error()) util.DefaultContext.Fatal("Invalid package string ", a, ": ", err.Error())
} }
toUninstall = append(toUninstall, pack) toUninstall = append(toUninstall, pack)
} }
@ -70,34 +70,35 @@ var replaceCmd = &cobra.Command{
for _, a := range f { for _, a := range f {
pack, err := helpers.ParsePackageStr(a) pack, err := helpers.ParsePackageStr(a)
if err != nil { if err != nil {
Fatal("Invalid package string ", a, ": ", err.Error()) util.DefaultContext.Fatal("Invalid package string ", a, ": ", err.Error())
} }
toAdd = append(toAdd, pack) toAdd = append(toAdd, pack)
} }
LuetCfg.GetSolverOptions().Implementation = solver.SingleCoreSimple util.DefaultContext.Config.GetSolverOptions().Implementation = solver.SingleCoreSimple
Debug("Solver", LuetCfg.GetSolverOptions().CompactString()) util.DefaultContext.Debug("Solver", util.DefaultContext.Config.GetSolverOptions().CompactString())
// Load config protect configs // Load config protect configs
installer.LoadConfigProtectConfs(LuetCfg) util.DefaultContext.Config.LoadConfigProtect(util.DefaultContext)
inst := installer.NewLuetInstaller(installer.LuetInstallerOptions{ inst := installer.NewLuetInstaller(installer.LuetInstallerOptions{
Concurrency: LuetCfg.GetGeneral().Concurrency, Concurrency: util.DefaultContext.Config.GetGeneral().Concurrency,
SolverOptions: *LuetCfg.GetSolverOptions(), SolverOptions: *util.DefaultContext.Config.GetSolverOptions(),
NoDeps: nodeps, NoDeps: nodeps,
Force: force, Force: force,
OnlyDeps: onlydeps, OnlyDeps: onlydeps,
PreserveSystemEssentialData: true, PreserveSystemEssentialData: true,
Ask: !yes, Ask: !yes,
DownloadOnly: downloadOnly, DownloadOnly: downloadOnly,
PackageRepositories: LuetCfg.SystemRepositories, PackageRepositories: util.DefaultContext.Config.SystemRepositories,
Context: util.DefaultContext,
}) })
system := &installer.System{Database: LuetCfg.GetSystemDB(), Target: LuetCfg.GetSystem().Rootfs} system := &installer.System{Database: util.DefaultContext.Config.GetSystemDB(), Target: util.DefaultContext.Config.GetSystem().Rootfs}
err := inst.Swap(toUninstall, toAdd, system) err := inst.Swap(toUninstall, toAdd, system)
if err != nil { if err != nil {
Fatal("Error: " + err.Error()) util.DefaultContext.Fatal("Error: " + err.Error())
} }
}, },
} }
@ -108,7 +109,7 @@ func init() {
replaceCmd.Flags().String("system-target", "", "System rootpath") replaceCmd.Flags().String("system-target", "", "System rootpath")
replaceCmd.Flags().String("system-engine", "", "System DB engine") replaceCmd.Flags().String("system-engine", "", "System DB engine")
replaceCmd.Flags().String("solver-type", "", "Solver strategy ( Defaults none, available: "+AvailableResolvers+" )") replaceCmd.Flags().String("solver-type", "", "Solver strategy ( Defaults none, available: "+types.AvailableResolvers+" )")
replaceCmd.Flags().Float32("solver-rate", 0.7, "Solver learning rate") replaceCmd.Flags().Float32("solver-rate", 0.7, "Solver learning rate")
replaceCmd.Flags().Float32("solver-discount", 1.0, "Solver discount rate") replaceCmd.Flags().Float32("solver-discount", 1.0, "Solver discount rate")
replaceCmd.Flags().Int("solver-attempts", 9000, "Solver maximum attempts") replaceCmd.Flags().Int("solver-attempts", 9000, "Solver maximum attempts")

View File

@ -22,10 +22,10 @@ import (
"strconv" "strconv"
"time" "time"
. "github.com/mudler/luet/pkg/config" "github.com/mudler/luet/cmd/util"
installer "github.com/mudler/luet/pkg/installer" installer "github.com/mudler/luet/pkg/installer"
"github.com/pterm/pterm"
. "github.com/logrusorgru/aurora"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
@ -43,7 +43,7 @@ func NewRepoListCommand() *cobra.Command {
quiet, _ := cmd.Flags().GetBool("quiet") quiet, _ := cmd.Flags().GetBool("quiet")
repoType, _ := cmd.Flags().GetString("type") repoType, _ := cmd.Flags().GetString("type")
for _, repo := range LuetCfg.SystemRepositories { for _, repo := range util.DefaultContext.Config.SystemRepositories {
if enable && !repo.Enable { if enable && !repo.Enable {
continue continue
} }
@ -58,17 +58,17 @@ func NewRepoListCommand() *cobra.Command {
fmt.Println(repo.Name) fmt.Println(repo.Name)
} else { } else {
if repo.Enable { if repo.Enable {
repoColor = Bold(BrightGreen(repo.Name)).String() repoColor = pterm.LightGreen(repo.Name)
} else { } else {
repoColor = Bold(BrightRed(repo.Name)).String() repoColor = pterm.LightRed(repo.Name)
} }
if repo.Description != "" { if repo.Description != "" {
repoText = Yellow(repo.Description).String() repoText = pterm.LightYellow(repo.Description)
} else { } else {
repoText = Yellow(repo.Urls[0]).String() repoText = pterm.LightYellow(repo.Urls[0])
} }
repobasedir := LuetCfg.GetSystem().GetRepoDatabaseDirPath(repo.Name) repobasedir := util.DefaultContext.Config.GetSystem().GetRepoDatabaseDirPath(repo.Name)
if repo.Cached { if repo.Cached {
r := installer.NewSystemRepository(repo) r := installer.NewSystemRepository(repo)
@ -76,8 +76,8 @@ func NewRepoListCommand() *cobra.Command {
installer.REPOSITORY_SPECFILE)) installer.REPOSITORY_SPECFILE))
if localRepo != nil { if localRepo != nil {
tsec, _ := strconv.ParseInt(localRepo.GetLastUpdate(), 10, 64) tsec, _ := strconv.ParseInt(localRepo.GetLastUpdate(), 10, 64)
repoRevision = Bold(Red(localRepo.GetRevision())).String() + repoRevision = pterm.LightRed(localRepo.GetRevision()) +
" - " + Bold(Green(time.Unix(tsec, 0).String())).String() " - " + pterm.LightGreen(time.Unix(tsec, 0).String())
} }
} }

View File

@ -17,9 +17,8 @@
package cmd_repo package cmd_repo
import ( import (
. "github.com/mudler/luet/pkg/config" "github.com/mudler/luet/cmd/util"
installer "github.com/mudler/luet/pkg/installer" installer "github.com/mudler/luet/pkg/installer"
. "github.com/mudler/luet/pkg/logger"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
@ -45,27 +44,27 @@ $> luet repo update repo1 repo2
if len(args) > 0 { if len(args) > 0 {
for _, rname := range args { for _, rname := range args {
repo, err := LuetCfg.GetSystemRepository(rname) repo, err := util.DefaultContext.Config.GetSystemRepository(rname)
if err != nil && !ignore { if err != nil && !ignore {
Fatal(err.Error()) util.DefaultContext.Fatal(err.Error())
} else if err != nil { } else if err != nil {
continue continue
} }
r := installer.NewSystemRepository(*repo) r := installer.NewSystemRepository(*repo)
_, err = r.Sync(force) _, err = r.Sync(util.DefaultContext, force)
if err != nil && !ignore { if err != nil && !ignore {
Fatal("Error on sync repository " + rname + ": " + err.Error()) util.DefaultContext.Fatal("Error on sync repository " + rname + ": " + err.Error())
} }
} }
} else { } else {
for _, repo := range LuetCfg.SystemRepositories { for _, repo := range util.DefaultContext.Config.SystemRepositories {
if repo.Cached && repo.Enable { if repo.Cached && repo.Enable {
r := installer.NewSystemRepository(repo) r := installer.NewSystemRepository(repo)
_, err := r.Sync(force) _, err := r.Sync(util.DefaultContext, force)
if err != nil && !ignore { if err != nil && !ignore {
Fatal("Error on sync repository " + r.GetName() + ": " + err.Error()) util.DefaultContext.Fatal("Error on sync repository " + r.GetName() + ": " + err.Error())
} }
} }
} }

View File

@ -19,31 +19,27 @@ import (
"fmt" "fmt"
"os" "os"
"github.com/marcsauter/single"
"github.com/mudler/luet/cmd/util" "github.com/mudler/luet/cmd/util"
bus "github.com/mudler/luet/pkg/bus" bus "github.com/mudler/luet/pkg/bus"
config "github.com/mudler/luet/pkg/config"
. "github.com/mudler/luet/pkg/logger"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/viper" "github.com/spf13/viper"
) )
var cfgFile string var cfgFile string
var Verbose bool var Verbose bool
var LockedCommands = []string{"install", "uninstall", "upgrade"}
const ( const (
LuetCLIVersion = "0.18.1" LuetCLIVersion = "0.18.1"
LuetEnvPrefix = "LUET" LuetEnvPrefix = "LUET"
license = `
Luet Copyright (C) 2019-2021 Ettore Di Giacinto
This program comes with ABSOLUTELY NO WARRANTY.
This is free software, and you are welcome to redistribute it
under certain conditions.
`
) )
var license = []string{
"Luet Copyright (C) 2019-2021 Ettore Di Giacinto",
"This program comes with ABSOLUTELY NO WARRANTY.",
"This is free software, and you are welcome to redistribute it under certain conditions.",
}
// Build time and commit information. // Build time and commit information.
// //
// ⚠️ WARNING: should only be set by "-ldflags". // ⚠️ WARNING: should only be set by "-ldflags".
@ -56,44 +52,6 @@ func version() string {
return fmt.Sprintf("%s-g%s %s", LuetCLIVersion, BuildCommit, BuildTime) return fmt.Sprintf("%s-g%s %s", LuetCLIVersion, BuildCommit, BuildTime)
} }
var bannerCommands = []string{"install", "build", "uninstall", "upgrade"}
func displayVersionBanner() {
display := false
if len(os.Args) > 1 {
for _, c := range bannerCommands {
if os.Args[1] == c {
display = true
}
}
}
if display {
util.IntroScreen()
Info("Luet version", version())
Info(license)
}
}
func handleLock() {
if os.Getenv("LUET_NOLOCK") != "true" {
if len(os.Args) > 1 {
for _, lockedCmd := range LockedCommands {
if os.Args[1] == lockedCmd {
s := single.New("luet")
if err := s.CheckLock(); err != nil && err == single.ErrAlreadyRunning {
Fatal("another instance of the app is already running, exiting")
} else if err != nil {
// Another error occurred, might be worth handling it as well
Fatal("failed to acquire exclusive app lock:", err.Error())
}
defer s.TryUnlock()
break
}
}
}
}
}
// RootCmd represents the base command when called without any subcommands // RootCmd represents the base command when called without any subcommands
var RootCmd = &cobra.Command{ var RootCmd = &cobra.Command{
Use: "luet", Use: "luet",
@ -123,18 +81,18 @@ To build a package, from a tree definition:
`, `,
Version: version(), Version: version(),
PersistentPreRun: func(cmd *cobra.Command, args []string) { PersistentPreRun: func(cmd *cobra.Command, args []string) {
err := util.InitContext(util.DefaultContext)
_, err := util.LoadConfig()
if err != nil { if err != nil {
Fatal("failed to load configuration:", err.Error()) util.DefaultContext.Error("failed to load configuration:", err.Error())
} }
util.DisplayVersionBanner(util.DefaultContext, util.IntroScreen, version, license)
// Initialize tmpdir prefix. TODO: Move this with LoadConfig // Initialize tmpdir prefix. TODO: Move this with LoadConfig
// directly on sub command to ensure the creation only when it's // directly on sub command to ensure the creation only when it's
// needed. // needed.
err = config.LuetCfg.GetSystem().InitTmpDir() err = util.DefaultContext.Config.GetSystem().InitTmpDir()
if err != nil { if err != nil {
Fatal("failed on init tmp basedir:", err.Error()) util.DefaultContext.Fatal("failed on init tmp basedir:", err.Error())
} }
viper.BindPFlag("plugin", cmd.Flags().Lookup("plugin")) viper.BindPFlag("plugin", cmd.Flags().Lookup("plugin"))
@ -143,17 +101,17 @@ To build a package, from a tree definition:
bus.Manager.Initialize(plugin...) bus.Manager.Initialize(plugin...)
if len(bus.Manager.Plugins) != 0 { if len(bus.Manager.Plugins) != 0 {
Info(":lollipop:Enabled plugins:") util.DefaultContext.Info(":lollipop:Enabled plugins:")
for _, p := range bus.Manager.Plugins { for _, p := range bus.Manager.Plugins {
Info("\t:arrow_right:", p.Name) util.DefaultContext.Info("\t:arrow_right:", p.Name)
} }
} }
}, },
PersistentPostRun: func(cmd *cobra.Command, args []string) { PersistentPostRun: func(cmd *cobra.Command, args []string) {
// Cleanup all tmp directories used by luet // Cleanup all tmp directories used by luet
err := config.LuetCfg.GetSystem().CleanupTmpDir() err := util.DefaultContext.Config.GetSystem().CleanupTmpDir()
if err != nil { if err != nil {
Warning("failed on cleanup tmpdir:", err.Error()) util.DefaultContext.Warning("failed on cleanup tmpdir:", err.Error())
} }
}, },
SilenceErrors: true, SilenceErrors: true,
@ -162,9 +120,7 @@ To build a package, from a tree definition:
// Execute adds all child commands to the root command sets flags appropriately. // Execute adds all child commands to the root command sets flags appropriately.
// This is called by main.main(). It only needs to happen once to the rootCmd. // This is called by main.main(). It only needs to happen once to the rootCmd.
func Execute() { func Execute() {
util.HandleLock(util.DefaultContext)
handleLock()
displayVersionBanner()
if err := RootCmd.Execute(); err != nil { if err := RootCmd.Execute(); err != nil {
fmt.Println(err) fmt.Println(err)
@ -173,5 +129,5 @@ func Execute() {
} }
func init() { func init() {
util.InitViper(RootCmd) util.InitViper(util.DefaultContext, RootCmd)
} }

View File

@ -19,13 +19,11 @@ import (
"strings" "strings"
"github.com/ghodss/yaml" "github.com/ghodss/yaml"
"github.com/jedib0t/go-pretty/table"
"github.com/jedib0t/go-pretty/v6/list"
"github.com/mudler/luet/cmd/util" "github.com/mudler/luet/cmd/util"
. "github.com/mudler/luet/pkg/config" "github.com/mudler/luet/pkg/api/core/types"
installer "github.com/mudler/luet/pkg/installer" installer "github.com/mudler/luet/pkg/installer"
. "github.com/mudler/luet/pkg/logger"
pkg "github.com/mudler/luet/pkg/package" pkg "github.com/mudler/luet/pkg/package"
"github.com/pterm/pterm"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/viper" "github.com/spf13/viper"
) )
@ -48,28 +46,47 @@ func (r PackageResult) String() string {
return fmt.Sprintf("%s/%s-%s required for %s", r.Category, r.Name, r.Version, r.Target) return fmt.Sprintf("%s/%s-%s required for %s", r.Category, r.Name, r.Version, r.Target)
} }
var rows table.Row = table.Row{"Package", "Category", "Name", "Version", "Repository", "Description", "License", "URI"} var rows []string = []string{"Package", "Category", "Name", "Version", "Repository", "License"}
func packageToRow(repo string, p pkg.Package) table.Row { func packageToRow(repo string, p pkg.Package) []string {
return table.Row{p.HumanReadableString(), p.GetCategory(), p.GetName(), p.GetVersion(), repo, p.GetDescription(), p.GetLicense(), strings.Join(p.GetURI(), "\n")} return []string{p.HumanReadableString(), p.GetCategory(), p.GetName(), p.GetVersion(), repo, p.GetLicense()}
} }
func packageToList(l list.Writer, repo string, p pkg.Package) { func packageToList(l *util.ListWriter, repo string, p pkg.Package) {
l.AppendItem(p.HumanReadableString()) l.AppendItem(pterm.BulletListItem{
l.Indent() Level: 0, Text: p.HumanReadableString(),
l.AppendItem(fmt.Sprintf("Category: %s", p.GetCategory())) TextStyle: pterm.NewStyle(pterm.FgCyan), Bullet: ">", BulletStyle: pterm.NewStyle(pterm.FgYellow),
l.AppendItem(fmt.Sprintf("Name: %s", p.GetName())) })
l.AppendItem(fmt.Sprintf("Version: %s", p.GetVersion())) l.AppendItem(pterm.BulletListItem{
l.AppendItem(fmt.Sprintf("Description: %s", p.GetDescription())) Level: 1, Text: fmt.Sprintf("Category: %s", p.GetCategory()),
l.AppendItem(fmt.Sprintf("Repository: %s ", repo)) Bullet: "->", BulletStyle: pterm.NewStyle(pterm.FgDarkGray),
l.AppendItem(fmt.Sprintf("Uri: %s ", strings.Join(p.GetURI(), "\n"))) })
l.UnIndent() l.AppendItem(pterm.BulletListItem{
Level: 1, Text: fmt.Sprintf("Name: %s", p.GetName()),
Bullet: "->", BulletStyle: pterm.NewStyle(pterm.FgDarkGray),
})
l.AppendItem(pterm.BulletListItem{
Level: 1, Text: fmt.Sprintf("Version: %s", p.GetVersion()),
Bullet: "->", BulletStyle: pterm.NewStyle(pterm.FgDarkGray),
})
l.AppendItem(pterm.BulletListItem{
Level: 1, Text: fmt.Sprintf("Description: %s", p.GetDescription()),
Bullet: "->", BulletStyle: pterm.NewStyle(pterm.FgDarkGray),
})
l.AppendItem(pterm.BulletListItem{
Level: 1, Text: fmt.Sprintf("Repository: %s ", repo),
Bullet: "->", BulletStyle: pterm.NewStyle(pterm.FgDarkGray),
})
l.AppendItem(pterm.BulletListItem{
Level: 1, Text: fmt.Sprintf("Uri: %s ", strings.Join(p.GetURI(), " ")),
Bullet: "->", BulletStyle: pterm.NewStyle(pterm.FgDarkGray),
})
} }
func searchLocally(term string, l list.Writer, t table.Writer, label, labelMatch, revdeps, hidden bool) Results { func searchLocally(term string, l *util.ListWriter, t *util.TableWriter, label, labelMatch, revdeps, hidden bool) Results {
var results Results var results Results
system := &installer.System{Database: LuetCfg.GetSystemDB(), Target: LuetCfg.GetSystem().Rootfs} system := &installer.System{Database: util.DefaultContext.Config.GetSystemDB(), Target: util.DefaultContext.Config.GetSystem().Rootfs}
var err error var err error
iMatches := pkg.Packages{} iMatches := pkg.Packages{}
@ -82,7 +99,7 @@ func searchLocally(term string, l list.Writer, t table.Writer, label, labelMatch
} }
if err != nil { if err != nil {
Fatal("Error: " + err.Error()) util.DefaultContext.Fatal("Error: " + err.Error())
} }
for _, pack := range iMatches { for _, pack := range iMatches {
@ -126,22 +143,23 @@ func searchLocally(term string, l list.Writer, t table.Writer, label, labelMatch
return results return results
} }
func searchOnline(term string, l list.Writer, t table.Writer, label, labelMatch, revdeps, hidden bool) Results { func searchOnline(term string, l *util.ListWriter, t *util.TableWriter, label, labelMatch, revdeps, hidden bool) Results {
var results Results var results Results
inst := installer.NewLuetInstaller( inst := installer.NewLuetInstaller(
installer.LuetInstallerOptions{ installer.LuetInstallerOptions{
Concurrency: LuetCfg.GetGeneral().Concurrency, Concurrency: util.DefaultContext.Config.GetGeneral().Concurrency,
SolverOptions: *LuetCfg.GetSolverOptions(), SolverOptions: *util.DefaultContext.Config.GetSolverOptions(),
PackageRepositories: LuetCfg.SystemRepositories, PackageRepositories: util.DefaultContext.Config.SystemRepositories,
Context: util.DefaultContext,
}, },
) )
synced, err := inst.SyncRepositories() synced, err := inst.SyncRepositories()
if err != nil { if err != nil {
Fatal("Error: " + err.Error()) util.DefaultContext.Fatal("Error: " + err.Error())
} }
Info("--- Search results (" + term + "): ---") util.DefaultContext.Info("--- Search results (" + term + "): ---")
matches := []installer.PackageMatch{} matches := []installer.PackageMatch{}
if label { if label {
@ -192,15 +210,15 @@ func searchOnline(term string, l list.Writer, t table.Writer, label, labelMatch,
} }
return results return results
} }
func searchLocalFiles(term string, l list.Writer, t table.Writer) Results { func searchLocalFiles(term string, l *util.ListWriter, t *util.TableWriter) Results {
var results Results var results Results
Info("--- Search results (" + term + "): ---") util.DefaultContext.Info("--- Search results (" + term + "): ---")
matches, _ := LuetCfg.GetSystemDB().FindPackageByFile(term) matches, _ := util.DefaultContext.Config.GetSystemDB().FindPackageByFile(term)
for _, pack := range matches { for _, pack := range matches {
t.AppendRow(packageToRow("system", pack)) t.AppendRow(packageToRow("system", pack))
packageToList(l, "system", pack) packageToList(l, "system", pack)
f, _ := LuetCfg.GetSystemDB().GetPackageFiles(pack) f, _ := util.DefaultContext.Config.GetSystemDB().GetPackageFiles(pack)
results.Packages = append(results.Packages, results.Packages = append(results.Packages,
PackageResult{ PackageResult{
Name: pack.GetName(), Name: pack.GetName(),
@ -215,22 +233,23 @@ func searchLocalFiles(term string, l list.Writer, t table.Writer) Results {
return results return results
} }
func searchFiles(term string, l list.Writer, t table.Writer) Results { func searchFiles(term string, l *util.ListWriter, t *util.TableWriter) Results {
var results Results var results Results
inst := installer.NewLuetInstaller( inst := installer.NewLuetInstaller(
installer.LuetInstallerOptions{ installer.LuetInstallerOptions{
Concurrency: LuetCfg.GetGeneral().Concurrency, Concurrency: util.DefaultContext.Config.GetGeneral().Concurrency,
SolverOptions: *LuetCfg.GetSolverOptions(), SolverOptions: *util.DefaultContext.Config.GetSolverOptions(),
PackageRepositories: LuetCfg.SystemRepositories, PackageRepositories: util.DefaultContext.Config.SystemRepositories,
Context: util.DefaultContext,
}, },
) )
synced, err := inst.SyncRepositories() synced, err := inst.SyncRepositories()
if err != nil { if err != nil {
Fatal("Error: " + err.Error()) util.DefaultContext.Fatal("Error: " + err.Error())
} }
Info("--- Search results (" + term + "): ---") util.DefaultContext.Info("--- Search results (" + term + "): ---")
matches := []installer.PackageMatch{} matches := []installer.PackageMatch{}
@ -297,7 +316,7 @@ Search can also return results in the terminal in different ways: as terminal ou
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
var results Results var results Results
if len(args) > 1 { if len(args) > 1 {
Fatal("Wrong number of arguments (expected 1)") util.DefaultContext.Fatal("Wrong number of arguments (expected 1)")
} else if len(args) == 0 { } else if len(args) == 0 {
args = []string{"."} args = []string{"."}
} }
@ -310,18 +329,18 @@ Search can also return results in the terminal in different ways: as terminal ou
tableMode, _ := cmd.Flags().GetBool("table") tableMode, _ := cmd.Flags().GetBool("table")
files, _ := cmd.Flags().GetBool("files") files, _ := cmd.Flags().GetBool("files")
util.SetSystemConfig() util.SetSystemConfig(util.DefaultContext)
util.SetSolverConfig() util.SetSolverConfig(util.DefaultContext)
out, _ := cmd.Flags().GetString("output") out, _ := cmd.Flags().GetString("output")
if out != "terminal" { if out != "terminal" {
LuetCfg.GetLogging().SetLogLevel("error") util.DefaultContext.Config.GetLogging().SetLogLevel("error")
} }
l := list.NewWriter() l := &util.ListWriter{}
t := table.NewWriter() t := &util.TableWriter{}
t.AppendHeader(rows) t.AppendRow(rows)
Debug("Solver", LuetCfg.GetSolverOptions().CompactString()) util.DefaultContext.Debug("Solver", util.DefaultContext.Config.GetSolverOptions().CompactString())
switch { switch {
case files && installed: case files && installed:
@ -334,14 +353,10 @@ Search can also return results in the terminal in different ways: as terminal ou
results = searchLocally(args[0], l, t, searchWithLabel, searchWithLabelMatch, revdeps, hidden) results = searchLocally(args[0], l, t, searchWithLabel, searchWithLabelMatch, revdeps, hidden)
} }
t.AppendFooter(rows)
t.SetStyle(table.StyleColoredBright)
l.SetStyle(list.StyleConnectedRounded)
if tableMode { if tableMode {
Info(t.Render()) t.Render()
} else { } else {
Info(l.Render()) l.Render()
} }
y, err := yaml.Marshal(results) y, err := yaml.Marshal(results)
@ -370,7 +385,7 @@ func init() {
searchCmd.Flags().String("system-engine", "", "System DB engine") searchCmd.Flags().String("system-engine", "", "System DB engine")
searchCmd.Flags().Bool("installed", false, "Search between system packages") searchCmd.Flags().Bool("installed", false, "Search between system packages")
searchCmd.Flags().String("solver-type", "", "Solver strategy ( Defaults none, available: "+AvailableResolvers+" )") searchCmd.Flags().String("solver-type", "", "Solver strategy ( Defaults none, available: "+types.AvailableResolvers+" )")
searchCmd.Flags().StringP("output", "o", "terminal", "Output format ( Defaults: terminal, available: json,yaml )") searchCmd.Flags().StringP("output", "o", "terminal", "Output format ( Defaults: terminal, available: json,yaml )")
searchCmd.Flags().Float32("solver-rate", 0.7, "Solver learning rate") searchCmd.Flags().Float32("solver-rate", 0.7, "Solver learning rate")
searchCmd.Flags().Float32("solver-discount", 1.0, "Solver discount rate") searchCmd.Flags().Float32("solver-discount", 1.0, "Solver discount rate")

View File

@ -18,7 +18,7 @@ import (
"net/http" "net/http"
"os" "os"
. "github.com/mudler/luet/pkg/logger" "github.com/mudler/luet/cmd/util"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/viper" "github.com/spf13/viper"
@ -41,15 +41,15 @@ var serverepoCmd = &cobra.Command{
http.Handle("/", http.FileServer(http.Dir(dir))) http.Handle("/", http.FileServer(http.Dir(dir)))
Info("Serving ", dir, " on HTTP port: ", port) util.DefaultContext.Info("Serving ", dir, " on HTTP port: ", port)
Fatal(http.ListenAndServe(address+":"+port, nil)) util.DefaultContext.Fatal(http.ListenAndServe(address+":"+port, nil))
}, },
} }
func init() { func init() {
path, err := os.Getwd() path, err := os.Getwd()
if err != nil { if err != nil {
Fatal(err) util.DefaultContext.Fatal(err)
} }
serverepoCmd.Flags().String("dir", path, "Packages folder (output from build)") serverepoCmd.Flags().String("dir", path, "Packages folder (output from build)")
serverepoCmd.Flags().String("port", "9090", "Listening port") serverepoCmd.Flags().String("port", "9090", "Listening port")

View File

@ -19,7 +19,7 @@ package cmd_tree
import ( import (
"fmt" "fmt"
. "github.com/mudler/luet/pkg/logger" "github.com/mudler/luet/cmd/util"
spectooling "github.com/mudler/luet/pkg/spectooling" spectooling "github.com/mudler/luet/pkg/spectooling"
tree "github.com/mudler/luet/pkg/tree" tree "github.com/mudler/luet/pkg/tree"
version "github.com/mudler/luet/pkg/versioner" version "github.com/mudler/luet/pkg/versioner"
@ -36,7 +36,7 @@ func NewTreeBumpCommand() *cobra.Command {
PreRun: func(cmd *cobra.Command, args []string) { PreRun: func(cmd *cobra.Command, args []string) {
df, _ := cmd.Flags().GetString("definition-file") df, _ := cmd.Flags().GetString("definition-file")
if df == "" { if df == "" {
Fatal("Mandatory definition.yaml path missing.") util.DefaultContext.Fatal("Mandatory definition.yaml path missing.")
} }
}, },
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
@ -45,34 +45,34 @@ func NewTreeBumpCommand() *cobra.Command {
pkgVersion, _ := cmd.Flags().GetString("pkg-version") pkgVersion, _ := cmd.Flags().GetString("pkg-version")
pack, err := tree.ReadDefinitionFile(spec) pack, err := tree.ReadDefinitionFile(spec)
if err != nil { if err != nil {
Fatal(err.Error()) util.DefaultContext.Fatal(err.Error())
} }
if pkgVersion != "" { if pkgVersion != "" {
validator := &version.WrappedVersioner{} validator := &version.WrappedVersioner{}
err := validator.Validate(pkgVersion) err := validator.Validate(pkgVersion)
if err != nil { if err != nil {
Fatal("Invalid version string: " + err.Error()) util.DefaultContext.Fatal("Invalid version string: " + err.Error())
} }
pack.SetVersion(pkgVersion) pack.SetVersion(pkgVersion)
} else { } else {
// Retrieve version build section with Gentoo parser // Retrieve version build section with Gentoo parser
err = pack.BumpBuildVersion() err = pack.BumpBuildVersion()
if err != nil { if err != nil {
Fatal("Error on increment build version: " + err.Error()) util.DefaultContext.Fatal("Error on increment build version: " + err.Error())
} }
} }
if toStdout { if toStdout {
data, err := spectooling.NewDefaultPackageSanitized(&pack).Yaml() data, err := spectooling.NewDefaultPackageSanitized(&pack).Yaml()
if err != nil { if err != nil {
Fatal("Error on yaml conversion: " + err.Error()) util.DefaultContext.Fatal("Error on yaml conversion: " + err.Error())
} }
fmt.Println(string(data)) fmt.Println(string(data))
} else { } else {
err = tree.WriteDefinitionFile(&pack, spec) err = tree.WriteDefinitionFile(&pack, spec)
if err != nil { if err != nil {
Fatal("Error on write definition file: " + err.Error()) util.DefaultContext.Fatal("Error on write definition file: " + err.Error())
} }
fmt.Printf("Bumped package %s/%s-%s.\n", pack.Category, pack.Name, pack.Version) fmt.Printf("Bumped package %s/%s-%s.\n", pack.Category, pack.Name, pack.Version)

View File

@ -20,15 +20,13 @@ import (
"fmt" "fmt"
"os" "os"
//. "github.com/mudler/luet/pkg/config"
"github.com/ghodss/yaml" "github.com/ghodss/yaml"
helpers "github.com/mudler/luet/cmd/helpers" helpers "github.com/mudler/luet/cmd/helpers"
"github.com/mudler/luet/cmd/util" "github.com/mudler/luet/cmd/util"
"github.com/mudler/luet/pkg/compiler" "github.com/mudler/luet/pkg/compiler"
"github.com/mudler/luet/pkg/compiler/backend" "github.com/mudler/luet/pkg/compiler/backend"
"github.com/mudler/luet/pkg/compiler/types/options" "github.com/mudler/luet/pkg/compiler/types/options"
. "github.com/mudler/luet/pkg/config"
. "github.com/mudler/luet/pkg/logger"
pkg "github.com/mudler/luet/pkg/package" pkg "github.com/mudler/luet/pkg/package"
"github.com/mudler/luet/pkg/solver" "github.com/mudler/luet/pkg/solver"
tree "github.com/mudler/luet/pkg/tree" tree "github.com/mudler/luet/pkg/tree"
@ -45,11 +43,11 @@ func NewTreeImageCommand() *cobra.Command {
PreRun: func(cmd *cobra.Command, args []string) { PreRun: func(cmd *cobra.Command, args []string) {
t, _ := cmd.Flags().GetStringArray("tree") t, _ := cmd.Flags().GetStringArray("tree")
if len(t) == 0 { if len(t) == 0 {
Fatal("Mandatory tree param missing.") util.DefaultContext.Fatal("Mandatory tree param missing.")
} }
if len(args) != 1 { if len(args) != 1 {
Fatal("Expects one package as parameter") util.DefaultContext.Fatal("Expects one package as parameter")
} }
util.BindValuesFlags(cmd) util.BindValuesFlags(cmd)
viper.BindPFlag("image-repository", cmd.Flags().Lookup("image-repository")) viper.BindPFlag("image-repository", cmd.Flags().Lookup("image-repository"))
@ -65,7 +63,7 @@ func NewTreeImageCommand() *cobra.Command {
out, _ := cmd.Flags().GetString("output") out, _ := cmd.Flags().GetString("output")
if out != "terminal" { if out != "terminal" {
LuetCfg.GetLogging().SetLogLevel("error") util.DefaultContext.Config.GetLogging().SetLogLevel("error")
} }
reciper := tree.NewCompilerRecipe(pkg.NewInMemoryDatabase(false)) reciper := tree.NewCompilerRecipe(pkg.NewInMemoryDatabase(false))
@ -73,20 +71,21 @@ func NewTreeImageCommand() *cobra.Command {
for _, t := range treePath { for _, t := range treePath {
err := reciper.Load(t) err := reciper.Load(t)
if err != nil { if err != nil {
Fatal("Error on load tree ", err) util.DefaultContext.Fatal("Error on load tree ", err)
} }
} }
compilerBackend := backend.NewSimpleDockerBackend() compilerBackend := backend.NewSimpleDockerBackend(util.DefaultContext)
opts := *LuetCfg.GetSolverOptions() opts := *util.DefaultContext.Config.GetSolverOptions()
opts.Options = solver.Options{Type: solver.SingleCoreSimple, Concurrency: 1} opts.Options = solver.Options{Type: solver.SingleCoreSimple, Concurrency: 1}
luetCompiler := compiler.NewLuetCompiler( luetCompiler := compiler.NewLuetCompiler(
compilerBackend, compilerBackend,
reciper.GetDatabase(), reciper.GetDatabase(),
options.WithBuildValues(values), options.WithBuildValues(values),
options.WithContext(util.DefaultContext),
options.WithPushRepository(imageRepository), options.WithPushRepository(imageRepository),
options.WithPullRepositories(pullRepo), options.WithPullRepositories(pullRepo),
options.WithTemplateFolder(util.TemplateFolders(false, treePath)), options.WithTemplateFolder(util.TemplateFolders(util.DefaultContext, false, treePath)),
options.WithSolverOptions(opts), options.WithSolverOptions(opts),
) )
@ -94,18 +93,18 @@ func NewTreeImageCommand() *cobra.Command {
pack, err := helpers.ParsePackageStr(a) pack, err := helpers.ParsePackageStr(a)
if err != nil { if err != nil {
Fatal("Invalid package string ", a, ": ", err.Error()) util.DefaultContext.Fatal("Invalid package string ", a, ": ", err.Error())
} }
spec, err := luetCompiler.FromPackage(pack) spec, err := luetCompiler.FromPackage(pack)
if err != nil { if err != nil {
Fatal("Error: " + err.Error()) util.DefaultContext.Fatal("Error: " + err.Error())
} }
ht := compiler.NewHashTree(reciper.GetDatabase()) ht := compiler.NewHashTree(reciper.GetDatabase())
hashtree, err := ht.Query(luetCompiler, spec) hashtree, err := ht.Query(luetCompiler, spec)
if err != nil { if err != nil {
Fatal("Error: " + err.Error()) util.DefaultContext.Fatal("Error: " + err.Error())
} }
for _, assertion := range hashtree.Solution { //highly dependent on the order for _, assertion := range hashtree.Solution { //highly dependent on the order
@ -145,7 +144,7 @@ func NewTreeImageCommand() *cobra.Command {
} }
path, err := os.Getwd() path, err := os.Getwd()
if err != nil { if err != nil {
Fatal(err) util.DefaultContext.Fatal(err)
} }
ans.Flags().StringP("output", "o", "terminal", "Output format ( Defaults: terminal, available: json,yaml )") ans.Flags().StringP("output", "o", "terminal", "Output format ( Defaults: terminal, available: json,yaml )")
ans.Flags().StringArrayP("tree", "t", []string{path}, "Path of the tree to use.") ans.Flags().StringArrayP("tree", "t", []string{path}, "Path of the tree to use.")

View File

@ -21,11 +21,9 @@ import (
"os" "os"
"sort" "sort"
//. "github.com/mudler/luet/pkg/config"
"github.com/ghodss/yaml" "github.com/ghodss/yaml"
helpers "github.com/mudler/luet/cmd/helpers" helpers "github.com/mudler/luet/cmd/helpers"
. "github.com/mudler/luet/pkg/config" "github.com/mudler/luet/cmd/util"
. "github.com/mudler/luet/pkg/logger"
pkg "github.com/mudler/luet/pkg/package" pkg "github.com/mudler/luet/pkg/package"
"github.com/mudler/luet/pkg/solver" "github.com/mudler/luet/pkg/solver"
tree "github.com/mudler/luet/pkg/tree" tree "github.com/mudler/luet/pkg/tree"
@ -75,13 +73,13 @@ func NewTreePkglistCommand() *cobra.Command {
PreRun: func(cmd *cobra.Command, args []string) { PreRun: func(cmd *cobra.Command, args []string) {
t, _ := cmd.Flags().GetStringArray("tree") t, _ := cmd.Flags().GetStringArray("tree")
if len(t) == 0 { if len(t) == 0 {
Fatal("Mandatory tree param missing.") util.DefaultContext.Fatal("Mandatory tree param missing.")
} }
revdeps, _ := cmd.Flags().GetBool("revdeps") revdeps, _ := cmd.Flags().GetBool("revdeps")
deps, _ := cmd.Flags().GetBool("deps") deps, _ := cmd.Flags().GetBool("deps")
if revdeps && deps { if revdeps && deps {
Fatal("Both revdeps and deps option used. Choice only one.") util.DefaultContext.Fatal("Both revdeps and deps option used. Choice only one.")
} }
}, },
@ -98,7 +96,7 @@ func NewTreePkglistCommand() *cobra.Command {
out, _ := cmd.Flags().GetString("output") out, _ := cmd.Flags().GetString("output")
if out != "terminal" { if out != "terminal" {
LuetCfg.GetLogging().SetLogLevel("error") util.DefaultContext.Config.GetLogging().SetLogLevel("error")
} }
var reciper tree.Builder var reciper tree.Builder
@ -111,7 +109,7 @@ func NewTreePkglistCommand() *cobra.Command {
for _, t := range treePath { for _, t := range treePath {
err := reciper.Load(t) err := reciper.Load(t)
if err != nil { if err != nil {
Fatal("Error on load tree ", err) util.DefaultContext.Fatal("Error on load tree ", err)
} }
} }
@ -126,11 +124,11 @@ func NewTreePkglistCommand() *cobra.Command {
regExcludes, err := helpers.CreateRegexArray(excludes) regExcludes, err := helpers.CreateRegexArray(excludes)
if err != nil { if err != nil {
Fatal(err.Error()) util.DefaultContext.Fatal(err.Error())
} }
regMatches, err := helpers.CreateRegexArray(matches) regMatches, err := helpers.CreateRegexArray(matches)
if err != nil { if err != nil {
Fatal(err.Error()) util.DefaultContext.Fatal(err.Error())
} }
plist := make([]string, 0) plist := make([]string, 0)
@ -194,12 +192,12 @@ func NewTreePkglistCommand() *cobra.Command {
solution, err := depSolver.Install(pkg.Packages{p}) solution, err := depSolver.Install(pkg.Packages{p})
if err != nil { if err != nil {
Fatal(err.Error()) util.DefaultContext.Fatal(err.Error())
} }
ass := solution.SearchByName(p.GetPackageName()) ass := solution.SearchByName(p.GetPackageName())
solution, err = solution.Order(reciper.GetDatabase(), ass.Package.GetFingerPrint()) solution, err = solution.Order(reciper.GetDatabase(), ass.Package.GetFingerPrint())
if err != nil { if err != nil {
Fatal(err.Error()) util.DefaultContext.Fatal(err.Error())
} }
for _, pa := range solution { for _, pa := range solution {
@ -270,7 +268,7 @@ func NewTreePkglistCommand() *cobra.Command {
} }
path, err := os.Getwd() path, err := os.Getwd()
if err != nil { if err != nil {
Fatal(err) util.DefaultContext.Fatal(err)
} }
ans.Flags().BoolP("buildtime", "b", false, "Build time match") ans.Flags().BoolP("buildtime", "b", false, "Build time match")
ans.Flags().StringP("output", "o", "terminal", "Output format ( Defaults: terminal, available: json,yaml )") ans.Flags().StringP("output", "o", "terminal", "Output format ( Defaults: terminal, available: json,yaml )")

View File

@ -26,8 +26,8 @@ import (
"sync" "sync"
helpers "github.com/mudler/luet/cmd/helpers" helpers "github.com/mudler/luet/cmd/helpers"
. "github.com/mudler/luet/pkg/config" "github.com/mudler/luet/cmd/util"
. "github.com/mudler/luet/pkg/logger"
pkg "github.com/mudler/luet/pkg/package" pkg "github.com/mudler/luet/pkg/package"
"github.com/mudler/luet/pkg/solver" "github.com/mudler/luet/pkg/solver"
tree "github.com/mudler/luet/pkg/tree" tree "github.com/mudler/luet/pkg/tree"
@ -104,7 +104,7 @@ func validatePackage(p pkg.Package, checkType string, opts *ValidateOpts, recipe
} else { } else {
errstr = "No packages" errstr = "No packages"
} }
Error(fmt.Sprintf("[%9s] %s/%s-%s: Broken. No versions could be found by database %s", util.DefaultContext.Error(fmt.Sprintf("[%9s] %s/%s-%s: Broken. No versions could be found by database %s",
checkType, checkType,
p.GetCategory(), p.GetName(), p.GetVersion(), p.GetCategory(), p.GetName(), p.GetVersion(),
errstr, errstr,
@ -134,7 +134,7 @@ func validatePackage(p pkg.Package, checkType string, opts *ValidateOpts, recipe
p.GetCategory(), p.GetName(), p.GetVersion(), p.GetCategory(), p.GetName(), p.GetVersion(),
err.Error(), err.Error(),
) )
Error(errstr) util.DefaultContext.Error(errstr)
return errors.New(errstr) return errors.New(errstr)
} }
@ -173,7 +173,7 @@ func validatePackage(p pkg.Package, checkType string, opts *ValidateOpts, recipe
} }
} }
Info(fmt.Sprintf("[%9s] Checking package ", checkType)+ util.DefaultContext.Info(fmt.Sprintf("[%9s] Checking package ", checkType)+
fmt.Sprintf("%s/%s-%s", p.GetCategory(), p.GetName(), p.GetVersion()), fmt.Sprintf("%s/%s-%s", p.GetCategory(), p.GetName(), p.GetVersion()),
"with", len(p.GetRequires()), "dependencies and", len(p.GetConflicts()), "conflicts.") "with", len(p.GetRequires()), "dependencies and", len(p.GetConflicts()), "conflicts.")
@ -201,7 +201,7 @@ func validatePackage(p pkg.Package, checkType string, opts *ValidateOpts, recipe
} else { } else {
errstr = "No packages" errstr = "No packages"
} }
Error(fmt.Sprintf("[%9s] %s/%s-%s: Broken Dep %s/%s-%s - %s", util.DefaultContext.Error(fmt.Sprintf("[%9s] %s/%s-%s: Broken Dep %s/%s-%s - %s",
checkType, checkType,
p.GetCategory(), p.GetName(), p.GetVersion(), p.GetCategory(), p.GetName(), p.GetVersion(),
r.GetCategory(), r.GetName(), r.GetVersion(), r.GetCategory(), r.GetName(), r.GetVersion(),
@ -221,12 +221,12 @@ func validatePackage(p pkg.Package, checkType string, opts *ValidateOpts, recipe
} else { } else {
Debug(fmt.Sprintf("[%9s] Find packages for dep", checkType), util.DefaultContext.Debug(fmt.Sprintf("[%9s] Find packages for dep", checkType),
fmt.Sprintf("%s/%s-%s", r.GetCategory(), r.GetName(), r.GetVersion())) fmt.Sprintf("%s/%s-%s", r.GetCategory(), r.GetName(), r.GetVersion()))
if opts.WithSolver { if opts.WithSolver {
Info(fmt.Sprintf("[%9s] :soap: [%2d/%2d] %s/%s-%s: %s/%s-%s", util.DefaultContext.Info(fmt.Sprintf("[%9s] :soap: [%2d/%2d] %s/%s-%s: %s/%s-%s",
checkType, checkType,
idx+1, len(all), idx+1, len(all),
p.GetCategory(), p.GetName(), p.GetVersion(), p.GetCategory(), p.GetName(), p.GetVersion(),
@ -236,15 +236,15 @@ func validatePackage(p pkg.Package, checkType string, opts *ValidateOpts, recipe
// Check if the solver is already been done for the deep // Check if the solver is already been done for the deep
_, err := cacheDeps.Get(r.HashFingerprint("")) _, err := cacheDeps.Get(r.HashFingerprint(""))
if err == nil { if err == nil {
Debug(fmt.Sprintf("[%9s] :direct_hit: Cache Hit for dep", checkType), util.DefaultContext.Debug(fmt.Sprintf("[%9s] :direct_hit: Cache Hit for dep", checkType),
fmt.Sprintf("%s/%s-%s", r.GetCategory(), r.GetName(), r.GetVersion())) fmt.Sprintf("%s/%s-%s", r.GetCategory(), r.GetName(), r.GetVersion()))
continue continue
} }
Spinner(22) util.DefaultContext.Spinner()
solution, err := depSolver.Install(pkg.Packages{r}) solution, err := depSolver.Install(pkg.Packages{r})
ass := solution.SearchByName(r.GetPackageName()) ass := solution.SearchByName(r.GetPackageName())
SpinnerStop() util.DefaultContext.SpinnerStop()
if err == nil { if err == nil {
if ass == nil { if ass == nil {
@ -255,7 +255,7 @@ func validatePackage(p pkg.Package, checkType string, opts *ValidateOpts, recipe
r.GetCategory(), r.GetName(), r.GetVersion(), r.GetCategory(), r.GetName(), r.GetVersion(),
)) ))
if LuetCfg.GetGeneral().Debug { if util.DefaultContext.Config.GetGeneral().Debug {
for idx, pa := range solution { for idx, pa := range solution {
fmt.Println(fmt.Sprintf("[%9s] %s/%s-%s: solution %d: %s", fmt.Println(fmt.Sprintf("[%9s] %s/%s-%s: solution %d: %s",
checkType, checkType,
@ -264,7 +264,7 @@ func validatePackage(p pkg.Package, checkType string, opts *ValidateOpts, recipe
} }
} }
Error(ans.Error()) util.DefaultContext.Error(ans.Error())
opts.IncrBrokenDeps() opts.IncrBrokenDeps()
validpkg = false validpkg = false
} else { } else {
@ -274,7 +274,7 @@ func validatePackage(p pkg.Package, checkType string, opts *ValidateOpts, recipe
if err != nil { if err != nil {
Error(fmt.Sprintf("[%9s] %s/%s-%s: solver broken for dep %s/%s-%s - %s", util.DefaultContext.Error(fmt.Sprintf("[%9s] %s/%s-%s: solver broken for dep %s/%s-%s - %s",
checkType, checkType,
p.GetCategory(), p.GetName(), p.GetVersion(), p.GetCategory(), p.GetName(), p.GetVersion(),
r.GetCategory(), r.GetName(), r.GetVersion(), r.GetCategory(), r.GetName(), r.GetVersion(),
@ -376,28 +376,28 @@ func initOpts(opts *ValidateOpts, onlyRuntime, onlyBuildtime, withSolver bool, t
opts.BuildtimeCacheDeps = pkg.NewInMemoryDatabase(false).(*pkg.InMemoryDatabase) opts.BuildtimeCacheDeps = pkg.NewInMemoryDatabase(false).(*pkg.InMemoryDatabase)
for _, treePath := range treePaths { for _, treePath := range treePaths {
Info(fmt.Sprintf("Loading :deciduous_tree: %s...", treePath)) util.DefaultContext.Info(fmt.Sprintf("Loading :deciduous_tree: %s...", treePath))
if opts.BuildtimeReciper != nil { if opts.BuildtimeReciper != nil {
err = opts.BuildtimeReciper.Load(treePath) err = opts.BuildtimeReciper.Load(treePath)
if err != nil { if err != nil {
Fatal("Error on load tree ", err) util.DefaultContext.Fatal("Error on load tree ", err)
} }
} }
if opts.RuntimeReciper != nil { if opts.RuntimeReciper != nil {
err = opts.RuntimeReciper.Load(treePath) err = opts.RuntimeReciper.Load(treePath)
if err != nil { if err != nil {
Fatal("Error on load tree ", err) util.DefaultContext.Fatal("Error on load tree ", err)
} }
} }
} }
opts.RegExcludes, err = helpers.CreateRegexArray(opts.Excludes) opts.RegExcludes, err = helpers.CreateRegexArray(opts.Excludes)
if err != nil { if err != nil {
Fatal(err.Error()) util.DefaultContext.Fatal(err.Error())
} }
opts.RegMatches, err = helpers.CreateRegexArray(opts.Matches) opts.RegMatches, err = helpers.CreateRegexArray(opts.Matches)
if err != nil { if err != nil {
Fatal(err.Error()) util.DefaultContext.Fatal(err.Error())
} }
} }
@ -417,16 +417,16 @@ func NewTreeValidateCommand() *cobra.Command {
onlyBuildtime, _ := cmd.Flags().GetBool("only-buildtime") onlyBuildtime, _ := cmd.Flags().GetBool("only-buildtime")
if len(treePaths) < 1 { if len(treePaths) < 1 {
Fatal("Mandatory tree param missing.") util.DefaultContext.Fatal("Mandatory tree param missing.")
} }
if onlyRuntime && onlyBuildtime { if onlyRuntime && onlyBuildtime {
Fatal("Both --only-runtime and --only-buildtime options are not possibile.") util.DefaultContext.Fatal("Both --only-runtime and --only-buildtime options are not possibile.")
} }
}, },
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
var reciper tree.Builder var reciper tree.Builder
concurrency := LuetCfg.GetGeneral().Concurrency concurrency := util.DefaultContext.Config.GetGeneral().Concurrency
withSolver, _ := cmd.Flags().GetBool("with-solver") withSolver, _ := cmd.Flags().GetBool("with-solver")
onlyRuntime, _ := cmd.Flags().GetBool("only-runtime") onlyRuntime, _ := cmd.Flags().GetBool("only-runtime")
@ -472,18 +472,18 @@ func NewTreeValidateCommand() *cobra.Command {
// fmt.Println("Broken packages:", brokenPkgs, "(", brokenDeps, "deps ).") // fmt.Println("Broken packages:", brokenPkgs, "(", brokenDeps, "deps ).")
if len(stringerrs) != 0 { if len(stringerrs) != 0 {
Error(fmt.Sprintf("Found %d broken packages and %d broken deps.", util.DefaultContext.Error(fmt.Sprintf("Found %d broken packages and %d broken deps.",
opts.BrokenPkgs, opts.BrokenDeps)) opts.BrokenPkgs, opts.BrokenDeps))
Fatal("Errors: " + strconv.Itoa(len(stringerrs))) util.DefaultContext.Fatal("Errors: " + strconv.Itoa(len(stringerrs)))
} else { } else {
Info("All good! :white_check_mark:") util.DefaultContext.Info("All good! :white_check_mark:")
os.Exit(0) os.Exit(0)
} }
}, },
} }
path, err := os.Getwd() path, err := os.Getwd()
if err != nil { if err != nil {
Fatal(err) util.DefaultContext.Fatal(err)
} }
ans.Flags().Bool("only-runtime", false, "Check only runtime dependencies.") ans.Flags().Bool("only-runtime", false, "Check only runtime dependencies.")
ans.Flags().Bool("only-buildtime", false, "Check only buildtime dependencies.") ans.Flags().Bool("only-buildtime", false, "Check only buildtime dependencies.")

View File

@ -17,9 +17,8 @@ package cmd
import ( import (
helpers "github.com/mudler/luet/cmd/helpers" helpers "github.com/mudler/luet/cmd/helpers"
"github.com/mudler/luet/cmd/util" "github.com/mudler/luet/cmd/util"
. "github.com/mudler/luet/pkg/config" "github.com/mudler/luet/pkg/api/core/types"
installer "github.com/mudler/luet/pkg/installer" installer "github.com/mudler/luet/pkg/installer"
. "github.com/mudler/luet/pkg/logger"
pkg "github.com/mudler/luet/pkg/package" pkg "github.com/mudler/luet/pkg/package"
"github.com/mudler/luet/pkg/solver" "github.com/mudler/luet/pkg/solver"
@ -45,7 +44,7 @@ var uninstallCmd = &cobra.Command{
pack, err := helpers.ParsePackageStr(a) pack, err := helpers.ParsePackageStr(a)
if err != nil { if err != nil {
Fatal("Invalid package string ", a, ": ", err.Error()) util.DefaultContext.Fatal("Invalid package string ", a, ": ", err.Error())
} }
toRemove = append(toRemove, pack) toRemove = append(toRemove, pack)
} }
@ -58,21 +57,21 @@ var uninstallCmd = &cobra.Command{
yes := viper.GetBool("yes") yes := viper.GetBool("yes")
keepProtected, _ := cmd.Flags().GetBool("keep-protected-files") keepProtected, _ := cmd.Flags().GetBool("keep-protected-files")
util.SetSystemConfig() util.SetSystemConfig(util.DefaultContext)
util.SetSolverConfig() util.SetSolverConfig(util.DefaultContext)
LuetCfg.ConfigProtectSkip = !keepProtected util.DefaultContext.Config.ConfigProtectSkip = !keepProtected
LuetCfg.GetSolverOptions().Implementation = solver.SingleCoreSimple util.DefaultContext.Config.GetSolverOptions().Implementation = solver.SingleCoreSimple
Debug("Solver", LuetCfg.GetSolverOptions().CompactString()) util.DefaultContext.Debug("Solver", util.DefaultContext.Config.GetSolverOptions().CompactString())
// Load config protect configs // Load config protect configs
installer.LoadConfigProtectConfs(LuetCfg) util.DefaultContext.Config.LoadConfigProtect(util.DefaultContext)
inst := installer.NewLuetInstaller(installer.LuetInstallerOptions{ inst := installer.NewLuetInstaller(installer.LuetInstallerOptions{
Concurrency: LuetCfg.GetGeneral().Concurrency, Concurrency: util.DefaultContext.Config.GetGeneral().Concurrency,
SolverOptions: *LuetCfg.GetSolverOptions(), SolverOptions: *util.DefaultContext.Config.GetSolverOptions(),
NoDeps: nodeps, NoDeps: nodeps,
Force: force, Force: force,
FullUninstall: full, FullUninstall: full,
@ -80,12 +79,13 @@ var uninstallCmd = &cobra.Command{
CheckConflicts: checkconflicts, CheckConflicts: checkconflicts,
Ask: !yes, Ask: !yes,
PreserveSystemEssentialData: true, PreserveSystemEssentialData: true,
Context: util.DefaultContext,
}) })
system := &installer.System{Database: LuetCfg.GetSystemDB(), Target: LuetCfg.GetSystem().Rootfs} system := &installer.System{Database: util.DefaultContext.Config.GetSystemDB(), Target: util.DefaultContext.Config.GetSystem().Rootfs}
if err := inst.Uninstall(system, toRemove...); err != nil { if err := inst.Uninstall(system, toRemove...); err != nil {
Fatal("Error: " + err.Error()) util.DefaultContext.Fatal("Error: " + err.Error())
} }
}, },
} }
@ -96,7 +96,7 @@ func init() {
uninstallCmd.Flags().String("system-target", "", "System rootpath") uninstallCmd.Flags().String("system-target", "", "System rootpath")
uninstallCmd.Flags().String("system-engine", "", "System DB engine") uninstallCmd.Flags().String("system-engine", "", "System DB engine")
uninstallCmd.Flags().String("solver-type", "", "Solver strategy ( Defaults none, available: "+AvailableResolvers+" )") uninstallCmd.Flags().String("solver-type", "", "Solver strategy ( Defaults none, available: "+types.AvailableResolvers+" )")
uninstallCmd.Flags().Float32("solver-rate", 0.7, "Solver learning rate") uninstallCmd.Flags().Float32("solver-rate", 0.7, "Solver learning rate")
uninstallCmd.Flags().Float32("solver-discount", 1.0, "Solver discount rate") uninstallCmd.Flags().Float32("solver-discount", 1.0, "Solver discount rate")
uninstallCmd.Flags().Int("solver-attempts", 9000, "Solver maximum attempts") uninstallCmd.Flags().Int("solver-attempts", 9000, "Solver maximum attempts")

View File

@ -16,9 +16,8 @@ package cmd
import ( import (
"github.com/mudler/luet/cmd/util" "github.com/mudler/luet/cmd/util"
. "github.com/mudler/luet/pkg/config" "github.com/mudler/luet/pkg/api/core/types"
installer "github.com/mudler/luet/pkg/installer" installer "github.com/mudler/luet/pkg/installer"
. "github.com/mudler/luet/pkg/logger"
"github.com/mudler/luet/pkg/solver" "github.com/mudler/luet/pkg/solver"
"github.com/spf13/cobra" "github.com/spf13/cobra"
@ -47,19 +46,19 @@ var upgradeCmd = &cobra.Command{
yes := viper.GetBool("yes") yes := viper.GetBool("yes")
downloadOnly, _ := cmd.Flags().GetBool("download-only") downloadOnly, _ := cmd.Flags().GetBool("download-only")
util.SetSystemConfig() util.SetSystemConfig(util.DefaultContext)
opts := util.SetSolverConfig() opts := util.SetSolverConfig(util.DefaultContext)
LuetCfg.GetSolverOptions().Implementation = solver.SingleCoreSimple util.DefaultContext.Config.GetSolverOptions().Implementation = solver.SingleCoreSimple
Debug("Solver", opts.CompactString()) util.DefaultContext.Debug("Solver", opts.CompactString())
// Load config protect configs // Load config protect configs
installer.LoadConfigProtectConfs(LuetCfg) util.DefaultContext.Config.LoadConfigProtect(util.DefaultContext)
inst := installer.NewLuetInstaller(installer.LuetInstallerOptions{ inst := installer.NewLuetInstaller(installer.LuetInstallerOptions{
Concurrency: LuetCfg.GetGeneral().Concurrency, Concurrency: util.DefaultContext.Config.GetGeneral().Concurrency,
SolverOptions: *LuetCfg.GetSolverOptions(), SolverOptions: *util.DefaultContext.Config.GetSolverOptions(),
Force: force, Force: force,
FullUninstall: full, FullUninstall: full,
NoDeps: nodeps, NoDeps: nodeps,
@ -69,12 +68,13 @@ var upgradeCmd = &cobra.Command{
PreserveSystemEssentialData: true, PreserveSystemEssentialData: true,
Ask: !yes, Ask: !yes,
DownloadOnly: downloadOnly, DownloadOnly: downloadOnly,
PackageRepositories: LuetCfg.SystemRepositories, PackageRepositories: util.DefaultContext.Config.SystemRepositories,
Context: util.DefaultContext,
}) })
system := &installer.System{Database: LuetCfg.GetSystemDB(), Target: LuetCfg.GetSystem().Rootfs} system := &installer.System{Database: util.DefaultContext.Config.GetSystemDB(), Target: util.DefaultContext.Config.GetSystem().Rootfs}
if err := inst.Upgrade(system); err != nil { if err := inst.Upgrade(system); err != nil {
Fatal("Error: " + err.Error()) util.DefaultContext.Fatal("Error: " + err.Error())
} }
}, },
} }
@ -84,7 +84,7 @@ func init() {
upgradeCmd.Flags().String("system-target", "", "System rootpath") upgradeCmd.Flags().String("system-target", "", "System rootpath")
upgradeCmd.Flags().String("system-engine", "", "System DB engine") upgradeCmd.Flags().String("system-engine", "", "System DB engine")
upgradeCmd.Flags().String("solver-type", "", "Solver strategy ( Defaults none, available: "+AvailableResolvers+" )") upgradeCmd.Flags().String("solver-type", "", "Solver strategy ( Defaults none, available: "+types.AvailableResolvers+" )")
upgradeCmd.Flags().Float32("solver-rate", 0.7, "Solver learning rate") upgradeCmd.Flags().Float32("solver-rate", 0.7, "Solver learning rate")
upgradeCmd.Flags().Float32("solver-discount", 1.0, "Solver discount rate") upgradeCmd.Flags().Float32("solver-discount", 1.0, "Solver discount rate")
upgradeCmd.Flags().Int("solver-attempts", 9000, "Solver maximum attempts") upgradeCmd.Flags().Int("solver-attempts", 9000, "Solver maximum attempts")

View File

@ -23,9 +23,8 @@ import (
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"github.com/docker/go-units" "github.com/docker/go-units"
config "github.com/mudler/luet/pkg/config" "github.com/mudler/luet/cmd/util"
"github.com/mudler/luet/pkg/helpers/docker" "github.com/mudler/luet/pkg/helpers/docker"
. "github.com/mudler/luet/pkg/logger"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
@ -42,7 +41,7 @@ func NewUnpackCommand() *cobra.Command {
PreRun: func(cmd *cobra.Command, args []string) { PreRun: func(cmd *cobra.Command, args []string) {
if len(args) != 2 { if len(args) != 2 {
Fatal("Expects an image and a path") util.DefaultContext.Fatal("Expects an image and a path")
} }
}, },
@ -51,7 +50,7 @@ func NewUnpackCommand() *cobra.Command {
image := args[0] image := args[0]
destination, err := filepath.Abs(args[1]) destination, err := filepath.Abs(args[1])
if err != nil { if err != nil {
Error("Invalid path %s", destination) util.DefaultContext.Error("Invalid path %s", destination)
os.Exit(1) os.Exit(1)
} }
@ -63,12 +62,12 @@ func NewUnpackCommand() *cobra.Command {
identity, _ := cmd.Flags().GetString("auth-identity-token") identity, _ := cmd.Flags().GetString("auth-identity-token")
registryToken, _ := cmd.Flags().GetString("auth-registry-token") registryToken, _ := cmd.Flags().GetString("auth-registry-token")
temp, err := config.LuetCfg.GetSystem().TempDir("contentstore") temp, err := util.DefaultContext.Config.GetSystem().TempDir("contentstore")
if err != nil { if err != nil {
Fatal("Cannot create a tempdir", err.Error()) util.DefaultContext.Fatal("Cannot create a tempdir", err.Error())
} }
Info("Downloading", image, "to", destination) util.DefaultContext.Info("Downloading", image, "to", destination)
auth := &types.AuthConfig{ auth := &types.AuthConfig{
Username: user, Username: user,
Password: pass, Password: pass,
@ -80,11 +79,11 @@ func NewUnpackCommand() *cobra.Command {
info, err := docker.DownloadAndExtractDockerImage(temp, image, destination, auth, verify) info, err := docker.DownloadAndExtractDockerImage(temp, image, destination, auth, verify)
if err != nil { if err != nil {
Error(err.Error()) util.DefaultContext.Error(err.Error())
os.Exit(1) os.Exit(1)
} }
Info(fmt.Sprintf("Pulled: %s %s", info.Target.Digest, info.Name)) util.DefaultContext.Info(fmt.Sprintf("Pulled: %s %s", info.Target.Digest, info.Name))
Info(fmt.Sprintf("Size: %s", units.BytesSize(float64(info.Target.Size)))) util.DefaultContext.Info(fmt.Sprintf("Size: %s", units.BytesSize(float64(info.Target.Size))))
}, },
} }

View File

@ -17,18 +17,24 @@ package util
import ( import (
"errors" "errors"
"os"
"path/filepath" "path/filepath"
"strings" "strings"
"github.com/marcsauter/single"
"github.com/pterm/pterm" "github.com/pterm/pterm"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/viper" "github.com/spf13/viper"
"github.com/mudler/luet/pkg/config" "github.com/mudler/luet/pkg/api/core/types"
. "github.com/mudler/luet/pkg/config"
"github.com/mudler/luet/pkg/installer" "github.com/mudler/luet/pkg/installer"
) )
var DefaultContext = types.NewContext()
var lockedCommands = []string{"install", "uninstall", "upgrade"}
var bannerCommands = []string{"install", "build", "uninstall", "upgrade"}
func BindSystemFlags(cmd *cobra.Command) { func BindSystemFlags(cmd *cobra.Command) {
viper.BindPFlag("system.database_path", cmd.Flags().Lookup("system-dbpath")) viper.BindPFlag("system.database_path", cmd.Flags().Lookup("system-dbpath"))
viper.BindPFlag("system.rootfs", cmd.Flags().Lookup("system-target")) viper.BindPFlag("system.rootfs", cmd.Flags().Lookup("system-target"))
@ -50,28 +56,28 @@ func ValuesFlags() []string {
return viper.GetStringSlice("values") return viper.GetStringSlice("values")
} }
func SetSystemConfig() { func SetSystemConfig(ctx *types.Context) {
dbpath := viper.GetString("system.database_path") dbpath := viper.GetString("system.database_path")
rootfs := viper.GetString("system.rootfs") rootfs := viper.GetString("system.rootfs")
engine := viper.GetString("system.database_engine") engine := viper.GetString("system.database_engine")
LuetCfg.System.DatabaseEngine = engine ctx.Config.System.DatabaseEngine = engine
LuetCfg.System.DatabasePath = dbpath ctx.Config.System.DatabasePath = dbpath
LuetCfg.System.SetRootFS(rootfs) ctx.Config.System.SetRootFS(rootfs)
} }
func SetSolverConfig() (c *config.LuetSolverOptions) { func SetSolverConfig(ctx *types.Context) (c *types.LuetSolverOptions) {
stype := viper.GetString("solver.type") stype := viper.GetString("solver.type")
discount := viper.GetFloat64("solver.discount") discount := viper.GetFloat64("solver.discount")
rate := viper.GetFloat64("solver.rate") rate := viper.GetFloat64("solver.rate")
attempts := viper.GetInt("solver.max_attempts") attempts := viper.GetInt("solver.max_attempts")
LuetCfg.GetSolverOptions().Type = stype ctx.Config.GetSolverOptions().Type = stype
LuetCfg.GetSolverOptions().LearnRate = float32(rate) ctx.Config.GetSolverOptions().LearnRate = float32(rate)
LuetCfg.GetSolverOptions().Discount = float32(discount) ctx.Config.GetSolverOptions().Discount = float32(discount)
LuetCfg.GetSolverOptions().MaxAttempts = attempts ctx.Config.GetSolverOptions().MaxAttempts = attempts
return &config.LuetSolverOptions{ return &types.LuetSolverOptions{
Type: stype, Type: stype,
LearnRate: float32(rate), LearnRate: float32(rate),
Discount: float32(discount), Discount: float32(discount),
@ -79,7 +85,7 @@ func SetSolverConfig() (c *config.LuetSolverOptions) {
} }
} }
func SetCliFinalizerEnvs(finalizerEnvs []string) error { func SetCliFinalizerEnvs(ctx *types.Context, finalizerEnvs []string) error {
if len(finalizerEnvs) > 0 { if len(finalizerEnvs) > 0 {
for _, v := range finalizerEnvs { for _, v := range finalizerEnvs {
idx := strings.Index(v, "=") idx := strings.Index(v, "=")
@ -87,7 +93,7 @@ func SetCliFinalizerEnvs(finalizerEnvs []string) error {
return errors.New("Found invalid runtime finalizer environment: " + v) return errors.New("Found invalid runtime finalizer environment: " + v)
} }
LuetCfg.SetFinalizerEnv(v[0:idx], v[idx+1:]) ctx.Config.SetFinalizerEnv(v[0:idx], v[idx+1:])
} }
} }
@ -96,13 +102,13 @@ func SetCliFinalizerEnvs(finalizerEnvs []string) error {
} }
// TemplateFolders returns the default folders which holds shared template between packages in a given tree path // TemplateFolders returns the default folders which holds shared template between packages in a given tree path
func TemplateFolders(fromRepo bool, treePaths []string) []string { func TemplateFolders(ctx *types.Context, fromRepo bool, treePaths []string) []string {
templateFolders := []string{} templateFolders := []string{}
for _, t := range treePaths { for _, t := range treePaths {
templateFolders = append(templateFolders, filepath.Join(t, "templates")) templateFolders = append(templateFolders, filepath.Join(t, "templates"))
} }
if fromRepo { if fromRepo {
for _, s := range installer.SystemRepositories(LuetCfg.SystemRepositories) { for _, s := range installer.SystemRepositories(ctx.Config.SystemRepositories) {
templateFolders = append(templateFolders, filepath.Join(s.TreePath, "templates")) templateFolders = append(templateFolders, filepath.Join(s.TreePath, "templates"))
} }
} }
@ -119,3 +125,42 @@ func IntroScreen() {
pterm.DefaultCenter.Print(pterm.DefaultHeader.WithFullWidth().WithBackgroundStyle(pterm.NewStyle(pterm.BgLightBlue)).WithMargin(10).Sprint("Luet - 0-deps container-based package manager")) pterm.DefaultCenter.Print(pterm.DefaultHeader.WithFullWidth().WithBackgroundStyle(pterm.NewStyle(pterm.BgLightBlue)).WithMargin(10).Sprint("Luet - 0-deps container-based package manager"))
} }
func HandleLock(c *types.Context) {
if os.Getenv("LUET_NOLOCK") != "true" {
if len(os.Args) > 1 {
for _, lockedCmd := range lockedCommands {
if os.Args[1] == lockedCmd {
s := single.New("luet")
if err := s.CheckLock(); err != nil && err == single.ErrAlreadyRunning {
c.Fatal("another instance of the app is already running, exiting")
} else if err != nil {
// Another error occurred, might be worth handling it as well
c.Fatal("failed to acquire exclusive app lock:", err.Error())
}
defer s.TryUnlock()
break
}
}
}
}
}
func DisplayVersionBanner(c *types.Context, banner func(), version func() string, license []string) {
display := false
if len(os.Args) > 1 {
for _, c := range bannerCommands {
if os.Args[1] == c {
display = true
}
}
}
if display {
banner()
pterm.DefaultCenter.Print(version())
for _, l := range license {
pterm.DefaultCenter.Print(l)
}
}
}

View File

@ -1,3 +1,18 @@
// Copyright © 2021 Ettore Di Giacinto <mudler@mocaccino.org>
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, see <http://www.gnu.org/licenses/>.
package util package util
import ( import (
@ -9,13 +24,10 @@ import (
"strings" "strings"
extensions "github.com/mudler/cobra-extensions" extensions "github.com/mudler/cobra-extensions"
. "github.com/mudler/luet/pkg/logger" "github.com/mudler/luet/pkg/api/core/types"
"github.com/mudler/luet/pkg/config"
helpers "github.com/mudler/luet/pkg/helpers" helpers "github.com/mudler/luet/pkg/helpers"
fileHelper "github.com/mudler/luet/pkg/helpers/file" fileHelper "github.com/mudler/luet/pkg/helpers/file"
"github.com/mudler/luet/pkg/helpers/terminal"
repo "github.com/mudler/luet/pkg/repository"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/viper" "github.com/spf13/viper"
@ -29,6 +41,7 @@ var cfgFile string
// initConfig reads in config file and ENV variables if set. // initConfig reads in config file and ENV variables if set.
func initConfig() { func initConfig() {
setDefaults(viper.GetViper())
// Luet support these priorities on read configuration file: // Luet support these priorities on read configuration file:
// - command line option (if available) // - command line option (if available)
// - $PWD/.luet.yaml // - $PWD/.luet.yaml
@ -46,7 +59,7 @@ func initConfig() {
// Retrieve pwd directory // Retrieve pwd directory
pwdDir, err := os.Getwd() pwdDir, err := os.Getwd()
if err != nil { if err != nil {
Error(err) fmt.Println(err)
os.Exit(1) os.Exit(1)
} }
homeDir := helpers.GetHomeDir() homeDir := helpers.GetHomeDir()
@ -69,56 +82,31 @@ func initConfig() {
replacer := strings.NewReplacer(".", "__") replacer := strings.NewReplacer(".", "__")
viper.SetEnvKeyReplacer(replacer) viper.SetEnvKeyReplacer(replacer)
viper.SetTypeByDefaultValue(true) viper.SetTypeByDefaultValue(true)
// If a config file is found, read it in.
viper.ReadInConfig()
} }
func LoadConfig() (cc config.LuetConfig, err error) { // InitContext inits the context by parsing the configurations from viper
setDefaults(viper.GetViper()) // this is meant to be run before each command to be able to parse any override from
initConfig() // the CLI/ENV
func InitContext(ctx *types.Context) (err error) {
// If a config file is found, read it in. err = viper.Unmarshal(&ctx.Config)
err = viper.ReadInConfig()
if err != nil { if err != nil {
return return
} }
err = viper.Unmarshal(&cc) // Inits the context with the configurations loaded
// It reads system repositories, sets logging, and all the
// context which is required to perform luet actions
err = ctx.Init()
if err != nil { if err != nil {
return return
} }
if terminal.IsTerminal(os.Stdout) { // no_spinner is not mapped in our configs
noSpinner := viper.GetBool("no_spinner") ctx.NoSpinner = viper.GetBool("no_spinner")
InitAurora()
if !noSpinner {
NewSpinner()
}
noColor := viper.GetBool("logging.color")
if noColor {
fmt.Println("Disabling color")
NoColor()
}
} else {
fmt.Println("Not a terminal, disabling color")
NoColor()
}
Debug("Using config file:", viper.ConfigFileUsed())
if cc.GetLogging().EnableLogFile && cc.GetLogging().Path != "" {
// Init zap logger
err = ZapLogger()
if err != nil {
return
}
}
// Load repositories
err = repo.LoadRepositories(&cc)
if err != nil {
return
}
config.LuetCfg = &cc
return return
} }
@ -133,8 +121,6 @@ func setDefaults(viper *viper.Viper) {
viper.SetDefault("general.concurrency", runtime.NumCPU()) viper.SetDefault("general.concurrency", runtime.NumCPU())
viper.SetDefault("general.debug", false) viper.SetDefault("general.debug", false)
viper.SetDefault("general.show_build_output", false) viper.SetDefault("general.show_build_output", false)
viper.SetDefault("general.spinner_ms", 100)
viper.SetDefault("general.spinner_charset", 22)
viper.SetDefault("general.fatal_warnings", false) viper.SetDefault("general.fatal_warnings", false)
u, err := user.Current() u, err := user.Current()
@ -158,7 +144,7 @@ func setDefaults(viper *viper.Viper) {
viper.SetDefault("config_from_host", true) viper.SetDefault("config_from_host", true)
viper.SetDefault("cache_repositories", []string{}) viper.SetDefault("cache_repositories", []string{})
viper.SetDefault("system_repositories", []string{}) viper.SetDefault("system_repositories", []string{})
viper.SetDefault("finalizer_envs", make(map[string]string, 0)) viper.SetDefault("finalizer_envs", make(map[string]string))
viper.SetDefault("solver.type", "") viper.SetDefault("solver.type", "")
viper.SetDefault("solver.rate", 0.7) viper.SetDefault("solver.rate", 0.7)
@ -166,7 +152,9 @@ func setDefaults(viper *viper.Viper) {
viper.SetDefault("solver.max_attempts", 9000) viper.SetDefault("solver.max_attempts", 9000)
} }
func InitViper(RootCmd *cobra.Command) { // InitViper inits a new viper
// this is meant to be run just once at beginning to setup the root command
func InitViper(ctx *types.Context, RootCmd *cobra.Command) {
cobra.OnInitialize(initConfig) cobra.OnInitialize(initConfig)
pflags := RootCmd.PersistentFlags() pflags := RootCmd.PersistentFlags()
pflags.StringVar(&cfgFile, "config", "", "config file (default is $HOME/.luet.yaml)") pflags.StringVar(&cfgFile, "config", "", "config file (default is $HOME/.luet.yaml)")
@ -174,11 +162,11 @@ func InitViper(RootCmd *cobra.Command) {
pflags.Bool("fatal", false, "Enables Warnings to exit") pflags.Bool("fatal", false, "Enables Warnings to exit")
pflags.Bool("enable-logfile", false, "Enable log to file") pflags.Bool("enable-logfile", false, "Enable log to file")
pflags.Bool("no-spinner", false, "Disable spinner.") pflags.Bool("no-spinner", false, "Disable spinner.")
pflags.Bool("color", config.LuetCfg.GetLogging().Color, "Enable/Disable color.") pflags.Bool("color", ctx.Config.GetLogging().Color, "Enable/Disable color.")
pflags.Bool("emoji", config.LuetCfg.GetLogging().EnableEmoji, "Enable/Disable emoji.") pflags.Bool("emoji", ctx.Config.GetLogging().EnableEmoji, "Enable/Disable emoji.")
pflags.Bool("skip-config-protect", config.LuetCfg.ConfigProtectSkip, pflags.Bool("skip-config-protect", ctx.Config.ConfigProtectSkip,
"Disable config protect analysis.") "Disable config protect analysis.")
pflags.StringP("logfile", "l", config.LuetCfg.GetLogging().Path, pflags.StringP("logfile", "l", ctx.Config.GetLogging().Path,
"Logfile path. Empty value disable log to file.") "Logfile path. Empty value disable log to file.")
pflags.StringSlice("plugin", []string{}, "A list of runtime plugins to load") pflags.StringSlice("plugin", []string{}, "A list of runtime plugins to load")
@ -186,9 +174,9 @@ func InitViper(RootCmd *cobra.Command) {
// Check if i can retrieve user informations. // Check if i can retrieve user informations.
_, err := user.Current() _, err := user.Current()
if err != nil { if err != nil {
Warning("failed to retrieve user identity:", err.Error()) ctx.Warning("failed to retrieve user identity:", err.Error())
} }
pflags.Bool("same-owner", config.LuetCfg.GetGeneral().SameOwner, "Maintain same owner on uncompress.") pflags.Bool("same-owner", ctx.Config.GetGeneral().SameOwner, "Maintain same owner on uncompress.")
pflags.Int("concurrency", runtime.NumCPU(), "Concurrency") pflags.Int("concurrency", runtime.NumCPU(), "Concurrency")
viper.BindPFlag("logging.color", pflags.Lookup("color")) viper.BindPFlag("logging.color", pflags.Lookup("color"))
@ -213,5 +201,4 @@ func InitViper(RootCmd *cobra.Command) {
cobraCmd := ex.CobraCommand() cobraCmd := ex.CobraCommand()
RootCmd.AddCommand(cobraCmd) RootCmd.AddCommand(cobraCmd)
} }
} }

View File

@ -1,5 +1,4 @@
// Copyright © 2019 Ettore Di Giacinto <mudler@gentoo.org> // Copyright © 2021 Ettore Di Giacinto <mudler@mocaccino.org>
// Daniele Rondina <geaaru@sabayonlinux.org>
// //
// This program is free software; you can redistribute it and/or modify // This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
@ -14,19 +13,30 @@
// You should have received a copy of the GNU General Public License along // You should have received a copy of the GNU General Public License along
// with this program; if not, see <http://www.gnu.org/licenses/>. // with this program; if not, see <http://www.gnu.org/licenses/>.
package repository_test package util
import ( import "github.com/pterm/pterm"
"testing"
. "github.com/mudler/luet/cmd/util" type TableWriter struct {
td pterm.TableData
. "github.com/onsi/ginkgo" }
. "github.com/onsi/gomega"
) func (l *TableWriter) AppendRow(item []string) {
l.td = append(l.td, item)
func TestSolver(t *testing.T) { }
RegisterFailHandler(Fail)
LoadConfig() func (l *TableWriter) Render() {
RunSpecs(t, "Repository Suite") pterm.DefaultTable.WithHasHeader().WithData(l.td).Render()
}
type ListWriter struct {
bb []pterm.BulletListItem
}
func (l *ListWriter) AppendItem(item pterm.BulletListItem) {
l.bb = append(l.bb, item)
}
func (l *ListWriter) Render() {
pterm.DefaultBulletList.WithItems(l.bb).Render()
} }

View File

@ -65,10 +65,7 @@ func (c *ConfigProtect) GetAnnotationDir() string {
return c.AnnotationDir return c.AnnotationDir
} }
func (c *ConfigProtect) Map(files []string) { func (c *ConfigProtect) Map(files []string, protected []ConfigProtectConfFile) {
if LuetCfg.ConfigProtectSkip {
return
}
for _, file := range files { for _, file := range files {
@ -76,8 +73,8 @@ func (c *ConfigProtect) Map(files []string) {
file = "/" + file file = "/" + file
} }
if len(LuetCfg.GetConfigProtectConfFiles()) > 0 { if len(protected) > 0 {
for _, conf := range LuetCfg.GetConfigProtectConfFiles() { for _, conf := range protected {
for _, dir := range conf.Directories { for _, dir := range conf.Directories {
// Note file is without / at begin (on unpack) // Note file is without / at begin (on unpack)
if strings.HasPrefix(file, filepath.Clean(dir)) { if strings.HasPrefix(file, filepath.Clean(dir)) {

View File

@ -17,7 +17,8 @@
package config_test package config_test
import ( import (
config "github.com/mudler/luet/pkg/config" config "github.com/mudler/luet/pkg/api/core/config"
"github.com/mudler/luet/pkg/api/core/types"
. "github.com/onsi/ginkgo" . "github.com/onsi/ginkgo"
. "github.com/onsi/gomega" . "github.com/onsi/gomega"
@ -28,7 +29,7 @@ var _ = Describe("Config", func() {
Context("Test config protect", func() { Context("Test config protect", func() {
It("Protect1", func() { It("Protect1", func() {
ctx := types.NewContext()
files := []string{ files := []string{
"etc/foo/my.conf", "etc/foo/my.conf",
"usr/bin/foo", "usr/bin/foo",
@ -36,7 +37,7 @@ var _ = Describe("Config", func() {
} }
cp := config.NewConfigProtect("/etc") cp := config.NewConfigProtect("/etc")
cp.Map(files) cp.Map(files, ctx.Config.ConfigProtectConfFiles)
Expect(cp.Protected("etc/foo/my.conf")).To(BeTrue()) Expect(cp.Protected("etc/foo/my.conf")).To(BeTrue())
Expect(cp.Protected("/etc/foo/my.conf")).To(BeTrue()) Expect(cp.Protected("/etc/foo/my.conf")).To(BeTrue())
@ -58,6 +59,7 @@ var _ = Describe("Config", func() {
}) })
It("Protect2", func() { It("Protect2", func() {
ctx := types.NewContext()
files := []string{ files := []string{
"etc/foo/my.conf", "etc/foo/my.conf",
@ -66,7 +68,7 @@ var _ = Describe("Config", func() {
} }
cp := config.NewConfigProtect("") cp := config.NewConfigProtect("")
cp.Map(files) cp.Map(files, ctx.Config.ConfigProtectConfFiles)
Expect(cp.Protected("etc/foo/my.conf")).To(BeFalse()) Expect(cp.Protected("etc/foo/my.conf")).To(BeFalse())
Expect(cp.Protected("/etc/foo/my.conf")).To(BeFalse()) Expect(cp.Protected("/etc/foo/my.conf")).To(BeFalse())
@ -84,6 +86,7 @@ var _ = Describe("Config", func() {
}) })
It("Protect3: Annotation dir without initial slash", func() { It("Protect3: Annotation dir without initial slash", func() {
ctx := types.NewContext()
files := []string{ files := []string{
"etc/foo/my.conf", "etc/foo/my.conf",
@ -92,7 +95,7 @@ var _ = Describe("Config", func() {
} }
cp := config.NewConfigProtect("etc") cp := config.NewConfigProtect("etc")
cp.Map(files) cp.Map(files, ctx.Config.ConfigProtectConfFiles)
Expect(cp.Protected("etc/foo/my.conf")).To(BeTrue()) Expect(cp.Protected("etc/foo/my.conf")).To(BeTrue())
Expect(cp.Protected("/etc/foo/my.conf")).To(BeTrue()) Expect(cp.Protected("/etc/foo/my.conf")).To(BeTrue())

View File

@ -19,14 +19,11 @@ package config_test
import ( import (
"testing" "testing"
. "github.com/mudler/luet/cmd/util"
. "github.com/onsi/ginkgo" . "github.com/onsi/ginkgo"
. "github.com/onsi/gomega" . "github.com/onsi/gomega"
) )
func TestSolver(t *testing.T) { func TestSolver(t *testing.T) {
RegisterFailHandler(Fail) RegisterFailHandler(Fail)
LoadConfig()
RunSpecs(t, "Config Suite") RunSpecs(t, "Config Suite")
} }

View File

@ -36,16 +36,17 @@ import (
"strings" "strings"
"sync" "sync"
config "github.com/mudler/luet/pkg/api/core/config"
types "github.com/mudler/luet/pkg/api/core/types"
bus "github.com/mudler/luet/pkg/bus" bus "github.com/mudler/luet/pkg/bus"
backend "github.com/mudler/luet/pkg/compiler/backend" backend "github.com/mudler/luet/pkg/compiler/backend"
compression "github.com/mudler/luet/pkg/compiler/types/compression" compression "github.com/mudler/luet/pkg/compiler/types/compression"
compilerspec "github.com/mudler/luet/pkg/compiler/types/spec" compilerspec "github.com/mudler/luet/pkg/compiler/types/spec"
. "github.com/mudler/luet/pkg/config"
"github.com/mudler/luet/pkg/helpers" "github.com/mudler/luet/pkg/helpers"
fileHelper "github.com/mudler/luet/pkg/helpers/file" fileHelper "github.com/mudler/luet/pkg/helpers/file"
. "github.com/mudler/luet/pkg/logger"
pkg "github.com/mudler/luet/pkg/package" pkg "github.com/mudler/luet/pkg/package"
"github.com/mudler/luet/pkg/solver" "github.com/mudler/luet/pkg/solver"
"github.com/pkg/errors" "github.com/pkg/errors"
yaml "gopkg.in/yaml.v2" yaml "gopkg.in/yaml.v2"
) )
@ -115,7 +116,6 @@ func (a *PackageArtifact) WriteYAML(dst string) error {
if err != nil { if err != nil {
return errors.Wrapf(err, "getting runtime package for '%s'", a.CompileSpec.Package.HumanReadableString()) return errors.Wrapf(err, "getting runtime package for '%s'", a.CompileSpec.Package.HumanReadableString())
} }
Debug(fmt.Sprintf("embedding runtime package (%s) definition to artifact metadata", a.CompileSpec.Package.HumanReadableString()))
a.Runtime = runtime a.Runtime = runtime
} }
@ -163,12 +163,12 @@ COPY . /`
} }
// CreateArtifactForFile creates a new artifact from the given file // CreateArtifactForFile creates a new artifact from the given file
func CreateArtifactForFile(s string, opts ...func(*PackageArtifact)) (*PackageArtifact, error) { func CreateArtifactForFile(ctx *types.Context, s string, opts ...func(*PackageArtifact)) (*PackageArtifact, error) {
if _, err := os.Stat(s); os.IsNotExist(err) { if _, err := os.Stat(s); os.IsNotExist(err) {
return nil, errors.Wrap(err, "artifact path doesn't exist") return nil, errors.Wrap(err, "artifact path doesn't exist")
} }
fileName := path.Base(s) fileName := path.Base(s)
archive, err := LuetCfg.GetSystem().TempDir("archive") archive, err := ctx.Config.GetSystem().TempDir("archive")
if err != nil { if err != nil {
return nil, errors.Wrap(err, "error met while creating tempdir for "+s) return nil, errors.Wrap(err, "error met while creating tempdir for "+s)
} }
@ -178,7 +178,7 @@ func CreateArtifactForFile(s string, opts ...func(*PackageArtifact)) (*PackageAr
return nil, errors.Wrapf(err, "error while copying %s to %s", s, dst) return nil, errors.Wrapf(err, "error while copying %s to %s", s, dst)
} }
artifact, err := LuetCfg.GetSystem().TempDir("artifact") artifact, err := ctx.Config.GetSystem().TempDir("artifact")
if err != nil { if err != nil {
return nil, errors.Wrap(err, "error met while creating tempdir for "+s) return nil, errors.Wrap(err, "error met while creating tempdir for "+s)
} }
@ -196,9 +196,9 @@ type ImageBuilder interface {
} }
// GenerateFinalImage takes an artifact and builds a Docker image with its content // GenerateFinalImage takes an artifact and builds a Docker image with its content
func (a *PackageArtifact) GenerateFinalImage(imageName string, b ImageBuilder, keepPerms bool) (backend.Options, error) { func (a *PackageArtifact) GenerateFinalImage(ctx *types.Context, imageName string, b ImageBuilder, keepPerms bool) (backend.Options, error) {
builderOpts := backend.Options{} builderOpts := backend.Options{}
archive, err := LuetCfg.GetSystem().TempDir("archive") archive, err := ctx.Config.GetSystem().TempDir("archive")
if err != nil { if err != nil {
return builderOpts, errors.Wrap(err, "error met while creating tempdir for "+a.Path) return builderOpts, errors.Wrap(err, "error met while creating tempdir for "+a.Path)
} }
@ -211,7 +211,7 @@ func (a *PackageArtifact) GenerateFinalImage(imageName string, b ImageBuilder, k
return builderOpts, errors.Wrap(err, "error met while creating tempdir for "+a.Path) return builderOpts, errors.Wrap(err, "error met while creating tempdir for "+a.Path)
} }
if err := a.Unpack(uncompressedFiles, keepPerms); err != nil { if err := a.Unpack(ctx, uncompressedFiles, keepPerms); err != nil {
return builderOpts, errors.Wrap(err, "error met while uncompressing artifact "+a.Path) return builderOpts, errors.Wrap(err, "error met while uncompressing artifact "+a.Path)
} }
@ -281,7 +281,7 @@ func (a *PackageArtifact) Compress(src string, concurrency int) error {
} }
os.RemoveAll(a.Path) // Remove original os.RemoveAll(a.Path) // Remove original
Debug("Removed artifact", a.Path) // Debug("Removed artifact", a.Path)
a.Path = zstdFile a.Path = zstdFile
return nil return nil
@ -315,7 +315,7 @@ func (a *PackageArtifact) Compress(src string, concurrency int) error {
} }
w.Close() w.Close()
os.RemoveAll(a.Path) // Remove original os.RemoveAll(a.Path) // Remove original
Debug("Removed artifact", a.Path) // Debug("Removed artifact", a.Path)
// a.CompressedPath = gzipfile // a.CompressedPath = gzipfile
a.Path = gzipfile a.Path = gzipfile
return nil return nil
@ -369,72 +369,74 @@ func hashFileContent(path string) (string, error) {
return base64.URLEncoding.EncodeToString(h.Sum(nil)), nil return base64.URLEncoding.EncodeToString(h.Sum(nil)), nil
} }
func tarModifierWrapperFunc(dst, path string, header *tar.Header, content io.Reader) (*tar.Header, []byte, error) { func tarModifierWrapperFunc(ctx *types.Context) func(dst, path string, header *tar.Header, content io.Reader) (*tar.Header, []byte, error) {
// If the destination path already exists I rename target file name with postfix. return func(dst, path string, header *tar.Header, content io.Reader) (*tar.Header, []byte, error) {
var destPath string // If the destination path already exists I rename target file name with postfix.
var destPath string
// Read data. TODO: We need change archive callback to permit to return a Reader // Read data. TODO: We need change archive callback to permit to return a Reader
buffer := bytes.Buffer{} buffer := bytes.Buffer{}
if content != nil { if content != nil {
if _, err := buffer.ReadFrom(content); err != nil { if _, err := buffer.ReadFrom(content); err != nil {
return nil, nil, err return nil, nil, err
}
}
tarHash := hashContent(buffer.Bytes())
// If file is not present on archive but is defined on mods
// I receive the callback. Prevent nil exception.
if header != nil {
switch header.Typeflag {
case tar.TypeReg:
destPath = filepath.Join(dst, path)
default:
// Nothing to do. I return original reader
return header, buffer.Bytes(), nil
}
existingHash := ""
f, err := os.Lstat(destPath)
if err == nil {
Debug("File exists already, computing hash for", destPath)
hash, herr := hashFileContent(destPath)
if herr == nil {
existingHash = hash
} }
} }
tarHash := hashContent(buffer.Bytes())
Debug("Existing file hash: ", existingHash, "Tar file hashsum: ", tarHash) // If file is not present on archive but is defined on mods
// We want to protect file only if the hash of the files are differing OR the file size are // I receive the callback. Prevent nil exception.
differs := (existingHash != "" && existingHash != tarHash) || (err != nil && f != nil && header.Size != f.Size()) if header != nil {
// Check if exists switch header.Typeflag {
if fileHelper.Exists(destPath) && differs { case tar.TypeReg:
for i := 1; i < 1000; i++ { destPath = filepath.Join(dst, path)
name := filepath.Join(filepath.Join(filepath.Dir(path), default:
fmt.Sprintf("._cfg%04d_%s", i, filepath.Base(path)))) // Nothing to do. I return original reader
return header, buffer.Bytes(), nil
}
if fileHelper.Exists(name) { existingHash := ""
continue f, err := os.Lstat(destPath)
if err == nil {
ctx.Debug("File exists already, computing hash for", destPath)
hash, herr := hashFileContent(destPath)
if herr == nil {
existingHash = hash
}
}
ctx.Debug("Existing file hash: ", existingHash, "Tar file hashsum: ", tarHash)
// We want to protect file only if the hash of the files are differing OR the file size are
differs := (existingHash != "" && existingHash != tarHash) || (err != nil && f != nil && header.Size != f.Size())
// Check if exists
if fileHelper.Exists(destPath) && differs {
for i := 1; i < 1000; i++ {
name := filepath.Join(filepath.Join(filepath.Dir(path),
fmt.Sprintf("._cfg%04d_%s", i, filepath.Base(path))))
if fileHelper.Exists(name) {
continue
}
ctx.Info(fmt.Sprintf("Found protected file %s. Creating %s.", destPath,
filepath.Join(dst, name)))
return &tar.Header{
Mode: header.Mode,
Typeflag: header.Typeflag,
PAXRecords: header.PAXRecords,
Name: name,
}, buffer.Bytes(), nil
} }
Info(fmt.Sprintf("Found protected file %s. Creating %s.", destPath,
filepath.Join(dst, name)))
return &tar.Header{
Mode: header.Mode,
Typeflag: header.Typeflag,
PAXRecords: header.PAXRecords,
Name: name,
}, buffer.Bytes(), nil
} }
} }
}
return header, buffer.Bytes(), nil return header, buffer.Bytes(), nil
}
} }
func (a *PackageArtifact) GetProtectFiles() []string { func (a *PackageArtifact) GetProtectFiles(ctx *types.Context) []string {
ans := []string{} ans := []string{}
annotationDir := "" annotationDir := ""
if !LuetCfg.ConfigProtectSkip { if !ctx.Config.ConfigProtectSkip {
// a.CompileSpec could be nil when artifact.Unpack is used for tree tarball // a.CompileSpec could be nil when artifact.Unpack is used for tree tarball
if a.CompileSpec != nil && if a.CompileSpec != nil &&
@ -446,8 +448,8 @@ func (a *PackageArtifact) GetProtectFiles() []string {
} }
// TODO: check if skip this if we have a.CompileSpec nil // TODO: check if skip this if we have a.CompileSpec nil
cp := NewConfigProtect(annotationDir) cp := config.NewConfigProtect(annotationDir)
cp.Map(a.Files) cp.Map(a.Files, ctx.Config.GetConfigProtectConfFiles())
// NOTE: for unpack we need files path without initial / // NOTE: for unpack we need files path without initial /
ans = cp.GetProtectFiles(false) ans = cp.GetProtectFiles(false)
@ -457,15 +459,15 @@ func (a *PackageArtifact) GetProtectFiles() []string {
} }
// Unpack Untar and decompress (TODO) to the given path // Unpack Untar and decompress (TODO) to the given path
func (a *PackageArtifact) Unpack(dst string, keepPerms bool) error { func (a *PackageArtifact) Unpack(ctx *types.Context, dst string, keepPerms bool) error {
if !strings.HasPrefix(dst, "/") { if !strings.HasPrefix(dst, "/") {
return errors.New("destination must be an absolute path") return errors.New("destination must be an absolute path")
} }
// Create // Create
protectedFiles := a.GetProtectFiles() protectedFiles := a.GetProtectFiles(ctx)
tarModifier := helpers.NewTarModifierWrapper(dst, tarModifierWrapperFunc) tarModifier := helpers.NewTarModifierWrapper(dst, tarModifierWrapperFunc(ctx))
switch a.CompressionType { switch a.CompressionType {
case compression.Zstandard: case compression.Zstandard:
@ -497,7 +499,7 @@ func (a *PackageArtifact) Unpack(dst string, keepPerms bool) error {
} }
err = helpers.UntarProtect(a.Path+".uncompressed", dst, err = helpers.UntarProtect(a.Path+".uncompressed", dst,
LuetCfg.GetGeneral().SameOwner, protectedFiles, tarModifier) ctx.Config.GetGeneral().SameOwner, protectedFiles, tarModifier)
if err != nil { if err != nil {
return err return err
} }
@ -530,14 +532,14 @@ func (a *PackageArtifact) Unpack(dst string, keepPerms bool) error {
} }
err = helpers.UntarProtect(a.Path+".uncompressed", dst, err = helpers.UntarProtect(a.Path+".uncompressed", dst,
LuetCfg.GetGeneral().SameOwner, protectedFiles, tarModifier) ctx.Config.GetGeneral().SameOwner, protectedFiles, tarModifier)
if err != nil { if err != nil {
return err return err
} }
return nil return nil
// Defaults to tar only (covers when "none" is supplied) // Defaults to tar only (covers when "none" is supplied)
default: default:
return helpers.UntarProtect(a.Path, dst, LuetCfg.GetGeneral().SameOwner, return helpers.UntarProtect(a.Path, dst, ctx.Config.GetGeneral().SameOwner,
protectedFiles, tarModifier) protectedFiles, tarModifier)
} }
return errors.New("Compression type must be supplied") return errors.New("Compression type must be supplied")
@ -630,15 +632,15 @@ type CopyJob struct {
Artifact string Artifact string
} }
func worker(i int, wg *sync.WaitGroup, s <-chan CopyJob) { func worker(ctx *types.Context, i int, wg *sync.WaitGroup, s <-chan CopyJob) {
defer wg.Done() defer wg.Done()
for job := range s { for job := range s {
_, err := os.Lstat(job.Dst) _, err := os.Lstat(job.Dst)
if err != nil { if err != nil {
Debug("Copying ", job.Src) ctx.Debug("Copying ", job.Src)
if err := fileHelper.DeepCopyFile(job.Src, job.Dst); err != nil { if err := fileHelper.DeepCopyFile(job.Src, job.Dst); err != nil {
Warning("Error copying", job, err) ctx.Warning("Error copying", job, err)
} }
} }
} }
@ -649,7 +651,6 @@ func compileRegexes(regexes []string) []*regexp.Regexp {
for _, i := range regexes { for _, i := range regexes {
r, e := regexp.Compile(i) r, e := regexp.Compile(i)
if e != nil { if e != nil {
Warning("Failed compiling regex:", e)
continue continue
} }
result = append(result, r) result = append(result, r)
@ -674,16 +675,16 @@ type ArtifactLayer struct {
} }
// ExtractArtifactFromDelta extracts deltas from ArtifactLayer from an image in tar format // ExtractArtifactFromDelta extracts deltas from ArtifactLayer from an image in tar format
func ExtractArtifactFromDelta(src, dst string, layers []ArtifactLayer, concurrency int, keepPerms bool, includes []string, excludes []string, t compression.Implementation) (*PackageArtifact, error) { func ExtractArtifactFromDelta(ctx *types.Context, src, dst string, layers []ArtifactLayer, concurrency int, keepPerms bool, includes []string, excludes []string, t compression.Implementation) (*PackageArtifact, error) {
archive, err := LuetCfg.GetSystem().TempDir("archive") archive, err := ctx.Config.GetSystem().TempDir("archive")
if err != nil { if err != nil {
return nil, errors.Wrap(err, "Error met while creating tempdir for archive") return nil, errors.Wrap(err, "Error met while creating tempdir for archive")
} }
defer os.RemoveAll(archive) // clean up defer os.RemoveAll(archive) // clean up
if strings.HasSuffix(src, ".tar") { if strings.HasSuffix(src, ".tar") {
rootfs, err := LuetCfg.GetSystem().TempDir("rootfs") rootfs, err := ctx.Config.GetSystem().TempDir("rootfs")
if err != nil { if err != nil {
return nil, errors.Wrap(err, "Error met while creating tempdir for rootfs") return nil, errors.Wrap(err, "Error met while creating tempdir for rootfs")
} }
@ -700,7 +701,7 @@ func ExtractArtifactFromDelta(src, dst string, layers []ArtifactLayer, concurren
var wg = new(sync.WaitGroup) var wg = new(sync.WaitGroup)
for i := 0; i < concurrency; i++ { for i := 0; i < concurrency; i++ {
wg.Add(1) wg.Add(1)
go worker(i, wg, toCopy) go worker(ctx, i, wg, toCopy)
} }
// Handle includes in spec. If specified they filter what gets in the package // Handle includes in spec. If specified they filter what gets in the package
@ -719,10 +720,10 @@ func ExtractArtifactFromDelta(src, dst string, layers []ArtifactLayer, concurren
} }
} }
for _, a := range l.Diffs.Changes { for _, a := range l.Diffs.Changes {
Debug("File ", a.Name, " changed") ctx.Debug("File ", a.Name, " changed")
} }
for _, a := range l.Diffs.Deletions { for _, a := range l.Diffs.Deletions {
Debug("File ", a.Name, " deleted") ctx.Debug("File ", a.Name, " deleted")
} }
} }
@ -740,10 +741,10 @@ func ExtractArtifactFromDelta(src, dst string, layers []ArtifactLayer, concurren
toCopy <- CopyJob{Src: filepath.Join(src, a.Name), Dst: filepath.Join(archive, a.Name), Artifact: a.Name} toCopy <- CopyJob{Src: filepath.Join(src, a.Name), Dst: filepath.Join(archive, a.Name), Artifact: a.Name}
} }
for _, a := range l.Diffs.Changes { for _, a := range l.Diffs.Changes {
Debug("File ", a.Name, " changed") ctx.Debug("File ", a.Name, " changed")
} }
for _, a := range l.Diffs.Deletions { for _, a := range l.Diffs.Deletions {
Debug("File ", a.Name, " deleted") ctx.Debug("File ", a.Name, " deleted")
} }
} }
@ -768,10 +769,10 @@ func ExtractArtifactFromDelta(src, dst string, layers []ArtifactLayer, concurren
} }
} }
for _, a := range l.Diffs.Changes { for _, a := range l.Diffs.Changes {
Debug("File ", a.Name, " changed") ctx.Debug("File ", a.Name, " changed")
} }
for _, a := range l.Diffs.Deletions { for _, a := range l.Diffs.Deletions {
Debug("File ", a.Name, " deleted") ctx.Debug("File ", a.Name, " deleted")
} }
} }
@ -780,14 +781,14 @@ func ExtractArtifactFromDelta(src, dst string, layers []ArtifactLayer, concurren
for _, l := range layers { for _, l := range layers {
// Consider d.Additions (and d.Changes? - warn at least) only // Consider d.Additions (and d.Changes? - warn at least) only
for _, a := range l.Diffs.Additions { for _, a := range l.Diffs.Additions {
Debug("File ", a.Name, " added") ctx.Debug("File ", a.Name, " added")
toCopy <- CopyJob{Src: filepath.Join(src, a.Name), Dst: filepath.Join(archive, a.Name), Artifact: a.Name} toCopy <- CopyJob{Src: filepath.Join(src, a.Name), Dst: filepath.Join(archive, a.Name), Artifact: a.Name}
} }
for _, a := range l.Diffs.Changes { for _, a := range l.Diffs.Changes {
Debug("File ", a.Name, " changed") ctx.Debug("File ", a.Name, " changed")
} }
for _, a := range l.Diffs.Deletions { for _, a := range l.Diffs.Deletions {
Debug("File ", a.Name, " deleted") ctx.Debug("File ", a.Name, " deleted")
} }
} }
} }

View File

@ -18,14 +18,11 @@ package artifact_test
import ( import (
"testing" "testing"
. "github.com/mudler/luet/cmd/util"
. "github.com/onsi/ginkgo" . "github.com/onsi/ginkgo"
. "github.com/onsi/gomega" . "github.com/onsi/gomega"
) )
func TestArtifact(t *testing.T) { func TestArtifact(t *testing.T) {
RegisterFailHandler(Fail) RegisterFailHandler(Fail)
LoadConfig()
RunSpecs(t, "Artifact Suite") RunSpecs(t, "Artifact Suite")
} }

View File

@ -20,11 +20,13 @@ import (
"os" "os"
"path/filepath" "path/filepath"
"github.com/mudler/luet/pkg/api/core/types"
. "github.com/mudler/luet/pkg/api/core/types/artifact" . "github.com/mudler/luet/pkg/api/core/types/artifact"
"github.com/mudler/luet/pkg/compiler" "github.com/mudler/luet/pkg/compiler"
. "github.com/mudler/luet/pkg/compiler/backend" . "github.com/mudler/luet/pkg/compiler/backend"
backend "github.com/mudler/luet/pkg/compiler/backend" backend "github.com/mudler/luet/pkg/compiler/backend"
compression "github.com/mudler/luet/pkg/compiler/types/compression" compression "github.com/mudler/luet/pkg/compiler/types/compression"
"github.com/mudler/luet/pkg/compiler/types/options"
compilerspec "github.com/mudler/luet/pkg/compiler/types/spec" compilerspec "github.com/mudler/luet/pkg/compiler/types/spec"
. "github.com/mudler/luet/pkg/compiler" . "github.com/mudler/luet/pkg/compiler"
@ -38,6 +40,7 @@ import (
var _ = Describe("Artifact", func() { var _ = Describe("Artifact", func() {
Context("Simple package build definition", func() { Context("Simple package build definition", func() {
ctx := types.NewContext()
It("Generates a verified delta", func() { It("Generates a verified delta", func() {
generalRecipe := tree.NewGeneralRecipe(pkg.NewInMemoryDatabase(false)) generalRecipe := tree.NewGeneralRecipe(pkg.NewInMemoryDatabase(false))
@ -47,7 +50,7 @@ var _ = Describe("Artifact", func() {
Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(1)) Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(1))
cc := NewLuetCompiler(nil, generalRecipe.GetDatabase()) cc := NewLuetCompiler(nil, generalRecipe.GetDatabase(), options.WithContext(types.NewContext()))
lspec, err := cc.FromPackage(&pkg.DefaultPackage{Name: "enman", Category: "app-admin", Version: "1.4.0"}) lspec, err := cc.FromPackage(&pkg.DefaultPackage{Name: "enman", Category: "app-admin", Version: "1.4.0"})
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
@ -81,7 +84,7 @@ WORKDIR /luetbuild
ENV PACKAGE_NAME=enman ENV PACKAGE_NAME=enman
ENV PACKAGE_VERSION=1.4.0 ENV PACKAGE_VERSION=1.4.0
ENV PACKAGE_CATEGORY=app-admin`)) ENV PACKAGE_CATEGORY=app-admin`))
b := NewSimpleDockerBackend() b := NewSimpleDockerBackend(ctx)
opts := backend.Options{ opts := backend.Options{
ImageName: "luet/base", ImageName: "luet/base",
SourcePath: tmpdir, SourcePath: tmpdir,
@ -115,7 +118,7 @@ RUN echo bar > /test2`))
Expect(b.BuildImage(opts2)).ToNot(HaveOccurred()) Expect(b.BuildImage(opts2)).ToNot(HaveOccurred())
Expect(b.ExportImage(opts2)).ToNot(HaveOccurred()) Expect(b.ExportImage(opts2)).ToNot(HaveOccurred())
Expect(fileHelper.Exists(filepath.Join(tmpdir, "output2.tar"))).To(BeTrue()) Expect(fileHelper.Exists(filepath.Join(tmpdir, "output2.tar"))).To(BeTrue())
diffs, err := compiler.GenerateChanges(b, opts, opts2) diffs, err := compiler.GenerateChanges(ctx, b, opts, opts2)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
artifacts := []ArtifactNode{{ artifacts := []ArtifactNode{{
@ -139,7 +142,7 @@ RUN echo bar > /test2`))
err = b.ExtractRootfs(backend.Options{ImageName: "test", Destination: rootfs}, false) err = b.ExtractRootfs(backend.Options{ImageName: "test", Destination: rootfs}, false)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
a, err := ExtractArtifactFromDelta(rootfs, filepath.Join(tmpdir, "package.tar"), diffs, 2, false, []string{}, []string{}, compression.None) a, err := ExtractArtifactFromDelta(ctx, rootfs, filepath.Join(tmpdir, "package.tar"), diffs, 2, false, []string{}, []string{}, compression.None)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
Expect(fileHelper.Exists(filepath.Join(tmpdir, "package.tar"))).To(BeTrue()) Expect(fileHelper.Exists(filepath.Join(tmpdir, "package.tar"))).To(BeTrue())
err = helpers.Untar(a.Path, unpacked, false) err = helpers.Untar(a.Path, unpacked, false)
@ -164,7 +167,7 @@ RUN echo bar > /test2`))
}) })
It("Generates packages images", func() { It("Generates packages images", func() {
b := NewSimpleDockerBackend() b := NewSimpleDockerBackend(ctx)
imageprefix := "foo/" imageprefix := "foo/"
testString := []byte(`funky test data`) testString := []byte(`funky test data`)
@ -190,7 +193,7 @@ RUN echo bar > /test2`))
err = a.Compress(tmpdir, 1) err = a.Compress(tmpdir, 1)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
resultingImage := imageprefix + "foo--1.0" resultingImage := imageprefix + "foo--1.0"
opts, err := a.GenerateFinalImage(resultingImage, b, false) opts, err := a.GenerateFinalImage(ctx, resultingImage, b, false)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
Expect(opts.ImageName).To(Equal(resultingImage)) Expect(opts.ImageName).To(Equal(resultingImage))
@ -215,7 +218,7 @@ RUN echo bar > /test2`))
}) })
It("Generates empty packages images", func() { It("Generates empty packages images", func() {
b := NewSimpleDockerBackend() b := NewSimpleDockerBackend(ctx)
imageprefix := "foo/" imageprefix := "foo/"
tmpdir, err := ioutil.TempDir(os.TempDir(), "artifact") tmpdir, err := ioutil.TempDir(os.TempDir(), "artifact")
@ -232,7 +235,7 @@ RUN echo bar > /test2`))
err = a.Compress(tmpdir, 1) err = a.Compress(tmpdir, 1)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
resultingImage := imageprefix + "foo--1.0" resultingImage := imageprefix + "foo--1.0"
opts, err := a.GenerateFinalImage(resultingImage, b, false) opts, err := a.GenerateFinalImage(ctx, resultingImage, b, false)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
Expect(opts.ImageName).To(Equal(resultingImage)) Expect(opts.ImageName).To(Equal(resultingImage))

View File

@ -20,6 +20,7 @@ import (
"os" "os"
"path/filepath" "path/filepath"
types "github.com/mudler/luet/pkg/api/core/types"
. "github.com/mudler/luet/pkg/api/core/types/artifact" . "github.com/mudler/luet/pkg/api/core/types/artifact"
compilerspec "github.com/mudler/luet/pkg/compiler/types/spec" compilerspec "github.com/mudler/luet/pkg/compiler/types/spec"
fileHelper "github.com/mudler/luet/pkg/helpers/file" fileHelper "github.com/mudler/luet/pkg/helpers/file"
@ -58,8 +59,8 @@ var _ = Describe("Cache", func() {
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
b := NewPackageArtifact(path) b := NewPackageArtifact(path)
ctx := types.NewContext()
err = b.Unpack(tmpdir, false) err = b.Unpack(ctx, tmpdir, false)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
Expect(fileHelper.Exists(filepath.Join(tmpdir, "foo"))).To(BeTrue()) Expect(fileHelper.Exists(filepath.Join(tmpdir, "foo"))).To(BeTrue())

View File

@ -15,17 +15,18 @@
// You should have received a copy of the GNU General Public License along // You should have received a copy of the GNU General Public License along
// with this program; if not, see <http://www.gnu.org/licenses/>. // with this program; if not, see <http://www.gnu.org/licenses/>.
package config package types
import ( import (
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"os" "os"
"path"
"path/filepath" "path/filepath"
"regexp"
"strings" "strings"
"time"
types "github.com/mudler/luet/pkg/api/core/types" "github.com/mudler/luet/pkg/api/core/config"
fileHelper "github.com/mudler/luet/pkg/helpers/file" fileHelper "github.com/mudler/luet/pkg/helpers/file"
pkg "github.com/mudler/luet/pkg/package" pkg "github.com/mudler/luet/pkg/package"
solver "github.com/mudler/luet/pkg/solver" solver "github.com/mudler/luet/pkg/solver"
@ -34,7 +35,6 @@ import (
"gopkg.in/yaml.v2" "gopkg.in/yaml.v2"
) )
var LuetCfg = &LuetConfig{}
var AvailableResolvers = strings.Join([]string{solver.QLearningResolverType}, " ") var AvailableResolvers = strings.Join([]string{solver.QLearningResolverType}, " ")
type LuetLoggingConfig struct { type LuetLoggingConfig struct {
@ -46,7 +46,7 @@ type LuetLoggingConfig struct {
JsonFormat bool `mapstructure:"json_format"` JsonFormat bool `mapstructure:"json_format"`
// Log level // Log level
Level string `mapstructure:"level"` Level LogLevel `mapstructure:"level"`
// Enable emoji // Enable emoji
EnableEmoji bool `mapstructure:"enable_emoji"` EnableEmoji bool `mapstructure:"enable_emoji"`
@ -59,8 +59,6 @@ type LuetGeneralConfig struct {
Concurrency int `yaml:"concurrency,omitempty" mapstructure:"concurrency"` Concurrency int `yaml:"concurrency,omitempty" mapstructure:"concurrency"`
Debug bool `yaml:"debug,omitempty" mapstructure:"debug"` Debug bool `yaml:"debug,omitempty" mapstructure:"debug"`
ShowBuildOutput bool `yaml:"show_build_output,omitempty" mapstructure:"show_build_output"` ShowBuildOutput bool `yaml:"show_build_output,omitempty" mapstructure:"show_build_output"`
SpinnerMs int `yaml:"spinner_ms,omitempty" mapstructure:"spinner_ms"`
SpinnerCharset int `yaml:"spinner_charset,omitempty" mapstructure:"spinner_charset"`
FatalWarns bool `yaml:"fatal_warnings,omitempty" mapstructure:"fatal_warnings"` FatalWarns bool `yaml:"fatal_warnings,omitempty" mapstructure:"fatal_warnings"`
} }
@ -171,33 +169,33 @@ type LuetConfig struct {
System LuetSystemConfig `yaml:"system" mapstructure:"system"` System LuetSystemConfig `yaml:"system" mapstructure:"system"`
Solver LuetSolverOptions `yaml:"solver,omitempty" mapstructure:"solver"` Solver LuetSolverOptions `yaml:"solver,omitempty" mapstructure:"solver"`
RepositoriesConfDir []string `yaml:"repos_confdir,omitempty" mapstructure:"repos_confdir"` RepositoriesConfDir []string `yaml:"repos_confdir,omitempty" mapstructure:"repos_confdir"`
ConfigProtectConfDir []string `yaml:"config_protect_confdir,omitempty" mapstructure:"config_protect_confdir"` ConfigProtectConfDir []string `yaml:"config_protect_confdir,omitempty" mapstructure:"config_protect_confdir"`
ConfigProtectSkip bool `yaml:"config_protect_skip,omitempty" mapstructure:"config_protect_skip"` ConfigProtectSkip bool `yaml:"config_protect_skip,omitempty" mapstructure:"config_protect_skip"`
ConfigFromHost bool `yaml:"config_from_host,omitempty" mapstructure:"config_from_host"` ConfigFromHost bool `yaml:"config_from_host,omitempty" mapstructure:"config_from_host"`
SystemRepositories types.LuetRepositories `yaml:"repositories,omitempty" mapstructure:"repositories"` SystemRepositories LuetRepositories `yaml:"repositories,omitempty" mapstructure:"repositories"`
FinalizerEnvs []LuetKV `json:"finalizer_envs,omitempty" yaml:"finalizer_envs,omitempty" mapstructure:"finalizer_envs,omitempty"` FinalizerEnvs []LuetKV `json:"finalizer_envs,omitempty" yaml:"finalizer_envs,omitempty" mapstructure:"finalizer_envs,omitempty"`
ConfigProtectConfFiles []ConfigProtectConfFile `yaml:"-" mapstructure:"-"` ConfigProtectConfFiles []config.ConfigProtectConfFile `yaml:"-" mapstructure:"-"`
} }
func (c *LuetConfig) GetSystemDB() pkg.PackageDatabase { func (c *LuetConfig) GetSystemDB() pkg.PackageDatabase {
switch LuetCfg.GetSystem().DatabaseEngine { switch c.GetSystem().DatabaseEngine {
case "boltdb": case "boltdb":
return pkg.NewBoltDatabase( return pkg.NewBoltDatabase(
filepath.Join(LuetCfg.GetSystem().GetSystemRepoDatabaseDirPath(), "luet.db")) filepath.Join(c.GetSystem().GetSystemRepoDatabaseDirPath(), "luet.db"))
default: default:
return pkg.NewInMemoryDatabase(true) return pkg.NewInMemoryDatabase(true)
} }
} }
func (c *LuetConfig) AddSystemRepository(r types.LuetRepository) { func (c *LuetConfig) AddSystemRepository(r LuetRepository) {
c.SystemRepositories = append(c.SystemRepositories, r) c.SystemRepositories = append(c.SystemRepositories, r)
} }
func (c *LuetConfig) GetFinalizerEnvsMap() map[string]string { func (c *LuetConfig) GetFinalizerEnvsMap() map[string]string {
ans := make(map[string]string, 0) ans := make(map[string]string)
for _, kv := range c.FinalizerEnvs { for _, kv := range c.FinalizerEnvs {
ans[kv.Key] = kv.Value ans[kv.Key] = kv.Value
@ -268,20 +266,81 @@ func (c *LuetConfig) YAML() ([]byte, error) {
return yaml.Marshal(c) return yaml.Marshal(c)
} }
func (c *LuetConfig) GetConfigProtectConfFiles() []ConfigProtectConfFile { func (c *LuetConfig) GetConfigProtectConfFiles() []config.ConfigProtectConfFile {
return c.ConfigProtectConfFiles return c.ConfigProtectConfFiles
} }
func (c *LuetConfig) AddConfigProtectConfFile(file *ConfigProtectConfFile) { func (c *LuetConfig) AddConfigProtectConfFile(file *config.ConfigProtectConfFile) {
if c.ConfigProtectConfFiles == nil { if c.ConfigProtectConfFiles == nil {
c.ConfigProtectConfFiles = []ConfigProtectConfFile{*file} c.ConfigProtectConfFiles = []config.ConfigProtectConfFile{*file}
} else { } else {
c.ConfigProtectConfFiles = append(c.ConfigProtectConfFiles, *file) c.ConfigProtectConfFiles = append(c.ConfigProtectConfFiles, *file)
} }
} }
func (c *LuetConfig) GetSystemRepository(name string) (*types.LuetRepository, error) { func (c *LuetConfig) LoadRepositories(ctx *Context) error {
var ans *types.LuetRepository = nil var regexRepo = regexp.MustCompile(`.yml$|.yaml$`)
var err error
rootfs := ""
// Respect the rootfs param on read repositories
if !c.ConfigFromHost {
rootfs, err = c.GetSystem().GetRootFsAbs()
if err != nil {
return err
}
}
for _, rdir := range c.RepositoriesConfDir {
rdir = filepath.Join(rootfs, rdir)
ctx.Debug("Parsing Repository Directory", rdir, "...")
files, err := ioutil.ReadDir(rdir)
if err != nil {
ctx.Debug("Skip dir", rdir, ":", err.Error())
continue
}
for _, file := range files {
if file.IsDir() {
continue
}
if !regexRepo.MatchString(file.Name()) {
ctx.Debug("File", file.Name(), "skipped.")
continue
}
content, err := ioutil.ReadFile(path.Join(rdir, file.Name()))
if err != nil {
ctx.Warning("On read file", file.Name(), ":", err.Error())
ctx.Warning("File", file.Name(), "skipped.")
continue
}
r, err := LoadRepository(content)
if err != nil {
ctx.Warning("On parse file", file.Name(), ":", err.Error())
ctx.Warning("File", file.Name(), "skipped.")
continue
}
if r.Name == "" || len(r.Urls) == 0 || r.Type == "" {
ctx.Warning("Invalid repository ", file.Name())
ctx.Warning("File", file.Name(), "skipped.")
continue
}
c.AddSystemRepository(*r)
}
}
return nil
}
func (c *LuetConfig) GetSystemRepository(name string) (*LuetRepository, error) {
var ans *LuetRepository = nil
for idx, repo := range c.SystemRepositories { for idx, repo := range c.SystemRepositories {
if repo.Name == name { if repo.Name == name {
@ -296,15 +355,78 @@ func (c *LuetConfig) GetSystemRepository(name string) (*types.LuetRepository, er
return ans, nil return ans, nil
} }
func (c *LuetGeneralConfig) GetSpinnerMs() time.Duration { func (c *LuetConfig) LoadConfigProtect(ctx *Context) error {
duration, err := time.ParseDuration(fmt.Sprintf("%dms", c.SpinnerMs)) var regexConfs = regexp.MustCompile(`.yml$`)
if err != nil { var err error
return 100 * time.Millisecond
rootfs := ""
// Respect the rootfs param on read repositories
if !c.ConfigFromHost {
rootfs, err = c.GetSystem().GetRootFsAbs()
if err != nil {
return err
}
} }
return duration
for _, cdir := range c.ConfigProtectConfDir {
cdir = filepath.Join(rootfs, cdir)
ctx.Debug("Parsing Config Protect Directory", cdir, "...")
files, err := ioutil.ReadDir(cdir)
if err != nil {
ctx.Debug("Skip dir", cdir, ":", err.Error())
continue
}
for _, file := range files {
if file.IsDir() {
continue
}
if !regexConfs.MatchString(file.Name()) {
ctx.Debug("File", file.Name(), "skipped.")
continue
}
content, err := ioutil.ReadFile(path.Join(cdir, file.Name()))
if err != nil {
ctx.Warning("On read file", file.Name(), ":", err.Error())
ctx.Warning("File", file.Name(), "skipped.")
continue
}
r, err := loadConfigProtectConFile(file.Name(), content)
if err != nil {
ctx.Warning("On parse file", file.Name(), ":", err.Error())
ctx.Warning("File", file.Name(), "skipped.")
continue
}
if r.Name == "" || len(r.Directories) == 0 {
ctx.Warning("Invalid config protect file", file.Name())
ctx.Warning("File", file.Name(), "skipped.")
continue
}
c.AddConfigProtectConfFile(r)
}
}
return nil
} }
func (c *LuetLoggingConfig) SetLogLevel(s string) { func loadConfigProtectConFile(filename string, data []byte) (*config.ConfigProtectConfFile, error) {
ans := config.NewConfigProtectConfFile(filename)
err := yaml.Unmarshal(data, &ans)
if err != nil {
return nil, err
}
return ans, nil
}
func (c *LuetLoggingConfig) SetLogLevel(s LogLevel) {
c.Level = s c.Level = s
} }

View File

@ -18,14 +18,11 @@ package types_test
import ( import (
"testing" "testing"
. "github.com/mudler/luet/cmd/util"
. "github.com/onsi/ginkgo" . "github.com/onsi/ginkgo"
. "github.com/onsi/gomega" . "github.com/onsi/gomega"
) )
func TestAPITypes(t *testing.T) { func TestAPITypes(t *testing.T) {
RegisterFailHandler(Fail) RegisterFailHandler(Fail)
LoadConfig()
RunSpecs(t, "Types Suite") RunSpecs(t, "Types Suite")
} }

View File

@ -0,0 +1,89 @@
// Copyright © 2019-2020 Ettore Di Giacinto <mudler@gentoo.org>
// Daniele Rondina <geaaru@sabayonlinux.org>
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, see <http://www.gnu.org/licenses/>.
package types_test
import (
"os"
"path/filepath"
"strings"
types "github.com/mudler/luet/pkg/api/core/types"
fileHelper "github.com/mudler/luet/pkg/helpers/file"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
var _ = Describe("Config", func() {
Context("Load Repository1", func() {
ctx := types.NewContext()
ctx.Config.RepositoriesConfDir = []string{
"../../../../tests/fixtures/repos.conf.d",
}
err := ctx.Config.LoadRepositories(ctx)
It("Check Load Repository 1", func() {
Expect(err).Should(BeNil())
Expect(len(ctx.Config.SystemRepositories)).Should(Equal(2))
Expect(ctx.Config.SystemRepositories[0].Name).Should(Equal("test1"))
Expect(ctx.Config.SystemRepositories[0].Priority).Should(Equal(999))
Expect(ctx.Config.SystemRepositories[0].Type).Should(Equal("disk"))
Expect(len(ctx.Config.SystemRepositories[0].Urls)).Should(Equal(1))
Expect(ctx.Config.SystemRepositories[0].Urls[0]).Should(Equal("tests/repos/test1"))
})
It("Chec Load Repository 2", func() {
Expect(err).Should(BeNil())
Expect(len(ctx.Config.SystemRepositories)).Should(Equal(2))
Expect(ctx.Config.SystemRepositories[1].Name).Should(Equal("test2"))
Expect(ctx.Config.SystemRepositories[1].Priority).Should(Equal(1000))
Expect(ctx.Config.SystemRepositories[1].Type).Should(Equal("disk"))
Expect(len(ctx.Config.SystemRepositories[1].Urls)).Should(Equal(1))
Expect(ctx.Config.SystemRepositories[1].Urls[0]).Should(Equal("tests/repos/test2"))
})
})
Context("Simple temporary directory creation", func() {
It("Create Temporary directory", func() {
ctx := types.NewContext()
ctx.Config.GetSystem().TmpDirBase = os.TempDir() + "/tmpluet"
tmpDir, err := ctx.Config.GetSystem().TempDir("test1")
Expect(err).ToNot(HaveOccurred())
Expect(strings.HasPrefix(tmpDir, filepath.Join(os.TempDir(), "tmpluet"))).To(BeTrue())
Expect(fileHelper.Exists(tmpDir)).To(BeTrue())
defer os.RemoveAll(tmpDir)
})
It("Create Temporary file", func() {
ctx := types.NewContext()
ctx.Config.GetSystem().TmpDirBase = os.TempDir() + "/tmpluet"
tmpFile, err := ctx.Config.GetSystem().TempFile("testfile1")
Expect(err).ToNot(HaveOccurred())
Expect(strings.HasPrefix(tmpFile.Name(), filepath.Join(os.TempDir(), "tmpluet"))).To(BeTrue())
Expect(fileHelper.Exists(tmpFile.Name())).To(BeTrue())
defer os.Remove(tmpFile.Name())
})
})
})

View File

@ -0,0 +1,380 @@
// Copyright © 2021 Ettore Di Giacinto <mudler@mocaccino.org>
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, see <http://www.gnu.org/licenses/>.
package types
import (
"context"
"fmt"
"os"
"path"
"path/filepath"
"regexp"
"runtime"
"strings"
"sync"
"github.com/kyokomi/emoji"
"github.com/mudler/luet/pkg/helpers/terminal"
"github.com/pterm/pterm"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
)
const (
ErrorLevel LogLevel = "error"
WarningLevel LogLevel = "warning"
InfoLevel LogLevel = "info"
SuccessLevel LogLevel = "success"
FatalLevel LogLevel = "fatal"
)
type Context struct {
context.Context
Config *LuetConfig
IsTerminal bool
NoSpinner bool
s *pterm.SpinnerPrinter
spinnerLock sync.Mutex
z *zap.Logger
}
func NewContext() *Context {
return &Context{
IsTerminal: terminal.IsTerminal(os.Stdout),
Config: &LuetConfig{
ConfigFromHost: true,
Logging: LuetLoggingConfig{},
General: LuetGeneralConfig{},
System: LuetSystemConfig{
DatabasePath: filepath.Join("var", "db", "packages"),
TmpDirBase: filepath.Join(os.TempDir(), "tmpluet")},
Solver: LuetSolverOptions{},
},
s: pterm.DefaultSpinner.WithShowTimer(false).WithRemoveWhenDone(true),
}
}
func (c *Context) Init() (err error) {
if c.IsTerminal {
if !c.Config.Logging.Color {
c.Debug("Disabling colors")
c.NoColor()
}
} else {
c.Debug("Not a terminal, disabling colors")
c.NoColor()
}
c.Debug("Colors", c.Config.GetLogging().Color)
c.Debug("Logging level", c.Config.GetLogging().Level)
c.Debug("Debug mode", c.Config.GetGeneral().Debug)
if c.Config.GetLogging().EnableLogFile && c.Config.GetLogging().Path != "" {
// Init zap logger
err = c.InitZap()
if err != nil {
return
}
}
// Load repositories
err = c.Config.LoadRepositories(c)
if err != nil {
return
}
return
}
func (c *Context) NoColor() {
pterm.DisableColor()
}
func (c *Context) Ask() bool {
var input string
c.Info("Do you want to continue with this operation? [y/N]: ")
_, err := fmt.Scanln(&input)
if err != nil {
return false
}
input = strings.ToLower(input)
if input == "y" || input == "yes" {
return true
}
return false
}
func (c *Context) InitZap() error {
var err error
if c.z == nil {
// TODO: test permission for open logfile.
cfg := zap.NewProductionConfig()
cfg.OutputPaths = []string{c.Config.GetLogging().Path}
cfg.Level = c.Config.GetLogging().Level.ZapLevel()
cfg.ErrorOutputPaths = []string{}
if c.Config.GetLogging().JsonFormat {
cfg.Encoding = "json"
} else {
cfg.Encoding = "console"
}
cfg.DisableCaller = true
cfg.DisableStacktrace = true
cfg.EncoderConfig.TimeKey = "time"
cfg.EncoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder
c.z, err = cfg.Build()
if err != nil {
fmt.Fprint(os.Stderr, "Error on initialize file logger: "+err.Error()+"\n")
return err
}
}
return nil
}
// Spinner starts the spinner
func (c *Context) Spinner() {
if !c.IsTerminal || c.NoSpinner {
return
}
c.spinnerLock.Lock()
defer c.spinnerLock.Unlock()
var confLevel int
if c.Config.GetGeneral().Debug {
confLevel = 3
} else {
confLevel = c.Config.GetLogging().Level.ToNumber()
}
if 2 > confLevel {
return
}
if !c.s.IsActive {
c.s, _ = c.s.Start()
}
}
func (c *Context) Screen(text string) {
pterm.DefaultHeader.WithBackgroundStyle(pterm.NewStyle(pterm.BgLightBlue)).WithMargin(2).Println(text)
//pterm.DefaultCenter.Print(pterm.DefaultHeader.WithFullWidth().WithBackgroundStyle(pterm.NewStyle(pterm.BgLightBlue)).WithMargin(10).Sprint(text))
}
func (c *Context) SpinnerText(suffix, prefix string) {
if !c.IsTerminal || c.NoSpinner {
return
}
c.spinnerLock.Lock()
defer c.spinnerLock.Unlock()
if c.Config.GetGeneral().Debug {
fmt.Printf("%s %s\n",
suffix, prefix,
)
} else {
c.s.UpdateText(suffix + prefix)
}
}
func (c *Context) SpinnerStop() {
if !c.IsTerminal {
return
}
c.spinnerLock.Lock()
defer c.spinnerLock.Unlock()
var confLevel int
if c.Config.GetGeneral().Debug {
confLevel = 3
} else {
confLevel = c.Config.GetLogging().Level.ToNumber()
}
if 2 > confLevel {
return
}
if c.s != nil {
c.s.Success()
}
}
func (c *Context) log2File(level LogLevel, msg string) {
switch level {
case FatalLevel:
c.z.Fatal(msg)
case ErrorLevel:
c.z.Error(msg)
case WarningLevel:
c.z.Warn(msg)
case InfoLevel, SuccessLevel:
c.z.Info(msg)
default:
c.z.Debug(msg)
}
}
func (c *Context) Msg(level LogLevel, ln bool, msg ...interface{}) {
var message string
var confLevel, msgLevel int
if c.Config.GetGeneral().Debug {
confLevel = 3
pterm.EnableDebugMessages()
} else {
confLevel = c.Config.GetLogging().Level.ToNumber()
}
msgLevel = level.ToNumber()
if msgLevel > confLevel {
return
}
for _, m := range msg {
message += " " + fmt.Sprintf("%v", m)
}
// Color message
levelMsg := message
if c.Config.GetLogging().Color {
switch level {
case WarningLevel:
levelMsg = pterm.LightYellow(":construction: warning" + message)
case InfoLevel, SuccessLevel:
levelMsg = pterm.LightGreen(message)
case ErrorLevel:
levelMsg = pterm.Red(message)
default:
levelMsg = pterm.Blue(message)
}
}
// Strip emoji if needed
if c.Config.GetLogging().EnableEmoji && c.IsTerminal {
levelMsg = emoji.Sprint(levelMsg)
} else {
re := regexp.MustCompile(`[:][\w]+[:]`)
levelMsg = re.ReplaceAllString(levelMsg, "")
}
if c.z != nil {
c.log2File(level, message)
}
// Print the message based on the level
switch level {
case SuccessLevel:
if ln {
pterm.Success.Println(levelMsg)
} else {
pterm.Success.Print(levelMsg)
}
case InfoLevel:
if ln {
pterm.Info.Println(levelMsg)
} else {
pterm.Info.Print(levelMsg)
}
case WarningLevel:
if ln {
pterm.Warning.Println(levelMsg)
} else {
pterm.Warning.Print(levelMsg)
}
case ErrorLevel:
if ln {
pterm.Error.Println(levelMsg)
} else {
pterm.Error.Print(levelMsg)
}
case FatalLevel:
if ln {
pterm.Fatal.Println(levelMsg)
} else {
pterm.Fatal.Print(levelMsg)
}
default:
if ln {
pterm.Debug.Println(levelMsg)
} else {
pterm.Debug.Print(levelMsg)
}
}
}
func (c *Context) Warning(mess ...interface{}) {
c.Msg("warning", true, mess...)
if c.Config.GetGeneral().FatalWarns {
os.Exit(2)
}
}
func (c *Context) Debug(mess ...interface{}) {
pc, file, line, ok := runtime.Caller(1)
if ok {
mess = append([]interface{}{fmt.Sprintf("(%s:#%d:%v)",
path.Base(file), line, runtime.FuncForPC(pc).Name())}, mess...)
}
c.Msg("debug", true, mess...)
}
func (c *Context) Info(mess ...interface{}) {
c.Msg("info", true, mess...)
}
func (c *Context) Success(mess ...interface{}) {
c.Msg("success", true, mess...)
}
func (c *Context) Error(mess ...interface{}) {
c.Msg("error", true, mess...)
}
func (c *Context) Fatal(mess ...interface{}) {
c.Error(mess...)
os.Exit(1)
}
type LogLevel string
func (level LogLevel) ToNumber() int {
switch level {
case ErrorLevel, FatalLevel:
return 0
case WarningLevel:
return 1
case InfoLevel, SuccessLevel:
return 2
default: // debug
return 3
}
}
func (level LogLevel) ZapLevel() zap.AtomicLevel {
switch level {
case FatalLevel:
return zap.NewAtomicLevelAt(zap.FatalLevel)
case ErrorLevel:
return zap.NewAtomicLevelAt(zap.ErrorLevel)
case WarningLevel:
return zap.NewAtomicLevelAt(zap.WarnLevel)
case InfoLevel, SuccessLevel:
return zap.NewAtomicLevelAt(zap.InfoLevel)
default:
return zap.NewAtomicLevelAt(zap.DebugLevel)
}
}

View File

@ -18,7 +18,7 @@ package types_test
import ( import (
"runtime" "runtime"
. "github.com/mudler/luet/pkg/api/core/types" types "github.com/mudler/luet/pkg/api/core/types"
. "github.com/onsi/ginkgo" . "github.com/onsi/ginkgo"
. "github.com/onsi/gomega" . "github.com/onsi/gomega"
) )
@ -26,23 +26,23 @@ import (
var _ = Describe("Types", func() { var _ = Describe("Types", func() {
Context("Repository detects underlying arch", func() { Context("Repository detects underlying arch", func() {
It("is enabled if arch is matching", func() { It("is enabled if arch is matching", func() {
r := LuetRepository{Arch: runtime.GOARCH} r := types.LuetRepository{Arch: runtime.GOARCH}
Expect(r.Enabled()).To(BeTrue()) Expect(r.Enabled()).To(BeTrue())
}) })
It("is disabled if arch is NOT matching", func() { It("is disabled if arch is NOT matching", func() {
r := LuetRepository{Arch: "foo"} r := types.LuetRepository{Arch: "foo"}
Expect(r.Enabled()).To(BeFalse()) Expect(r.Enabled()).To(BeFalse())
}) })
It("is enabled if arch is NOT matching and enabled is true", func() { It("is enabled if arch is NOT matching and enabled is true", func() {
r := LuetRepository{Arch: "foo", Enable: true} r := types.LuetRepository{Arch: "foo", Enable: true}
Expect(r.Enabled()).To(BeTrue()) Expect(r.Enabled()).To(BeTrue())
}) })
It("enabled is true", func() { It("enabled is true", func() {
r := LuetRepository{Enable: true} r := types.LuetRepository{Enable: true}
Expect(r.Enabled()).To(BeTrue()) Expect(r.Enabled()).To(BeTrue())
}) })
It("enabled is false", func() { It("enabled is false", func() {
r := LuetRepository{Enable: false} r := types.LuetRepository{Enable: false}
Expect(r.Enabled()).To(BeFalse()) Expect(r.Enabled()).To(BeFalse())
}) })
}) })

View File

@ -7,23 +7,21 @@ import (
"path/filepath" "path/filepath"
"strings" "strings"
"github.com/mudler/luet/pkg/api/core/types"
artifact "github.com/mudler/luet/pkg/api/core/types/artifact" artifact "github.com/mudler/luet/pkg/api/core/types/artifact"
"github.com/mudler/luet/pkg/compiler/backend" "github.com/mudler/luet/pkg/compiler/backend"
"github.com/mudler/luet/pkg/config"
"github.com/pkg/errors" "github.com/pkg/errors"
. "github.com/mudler/luet/pkg/logger"
) )
func NewBackend(s string) (CompilerBackend, error) { func NewBackend(ctx *types.Context, s string) (CompilerBackend, error) {
var compilerBackend CompilerBackend var compilerBackend CompilerBackend
switch s { switch s {
case backend.ImgBackend: case backend.ImgBackend:
compilerBackend = backend.NewSimpleImgBackend() compilerBackend = backend.NewSimpleImgBackend(ctx)
case backend.DockerBackend: case backend.DockerBackend:
compilerBackend = backend.NewSimpleDockerBackend() compilerBackend = backend.NewSimpleDockerBackend(ctx)
default: default:
return nil, errors.New("invalid backend. Unsupported") return nil, errors.New("invalid backend. Unsupported")
} }
@ -73,11 +71,11 @@ type CompilerBackend interface {
// } // }
// } // }
// ] // ]
func GenerateChanges(b CompilerBackend, fromImage, toImage backend.Options) ([]artifact.ArtifactLayer, error) { func GenerateChanges(ctx *types.Context, b CompilerBackend, fromImage, toImage backend.Options) ([]artifact.ArtifactLayer, error) {
res := artifact.ArtifactLayer{FromImage: fromImage.ImageName, ToImage: toImage.ImageName} res := artifact.ArtifactLayer{FromImage: fromImage.ImageName, ToImage: toImage.ImageName}
tmpdiffs, err := config.LuetCfg.GetSystem().TempDir("extraction") tmpdiffs, err := ctx.Config.GetSystem().TempDir("extraction")
if err != nil { if err != nil {
return []artifact.ArtifactLayer{}, errors.Wrap(err, "Error met while creating tempdir for rootfs") return []artifact.ArtifactLayer{}, errors.Wrap(err, "Error met while creating tempdir for rootfs")
} }
@ -99,7 +97,7 @@ func GenerateChanges(b CompilerBackend, fromImage, toImage backend.Options) ([]a
ImageName: fromImage.ImageName, ImageName: fromImage.ImageName,
Destination: srcRootFS, Destination: srcRootFS,
} }
Debug("Extracting source image", fromImage.ImageName) ctx.Debug("Extracting source image", fromImage.ImageName)
err = b.ExtractRootfs(srcImageExtract, false) // No need to keep permissions as we just collect file diffs err = b.ExtractRootfs(srcImageExtract, false) // No need to keep permissions as we just collect file diffs
if err != nil { if err != nil {
return []artifact.ArtifactLayer{}, errors.Wrap(err, "Error met while unpacking src image "+fromImage.ImageName) return []artifact.ArtifactLayer{}, errors.Wrap(err, "Error met while unpacking src image "+fromImage.ImageName)
@ -109,7 +107,7 @@ func GenerateChanges(b CompilerBackend, fromImage, toImage backend.Options) ([]a
ImageName: toImage.ImageName, ImageName: toImage.ImageName,
Destination: dstRootFS, Destination: dstRootFS,
} }
Debug("Extracting destination image", toImage.ImageName) ctx.Debug("Extracting destination image", toImage.ImageName)
err = b.ExtractRootfs(dstImageExtract, false) err = b.ExtractRootfs(dstImageExtract, false)
if err != nil { if err != nil {
return []artifact.ArtifactLayer{}, errors.Wrap(err, "Error met while unpacking dst image "+toImage.ImageName) return []artifact.ArtifactLayer{}, errors.Wrap(err, "Error met while unpacking dst image "+toImage.ImageName)
@ -182,10 +180,10 @@ func GenerateChanges(b CompilerBackend, fromImage, toImage backend.Options) ([]a
diffs := []artifact.ArtifactLayer{res} diffs := []artifact.ArtifactLayer{res}
if config.LuetCfg.GetGeneral().Debug { if ctx.Config.GetGeneral().Debug {
summary := ComputeArtifactLayerSummary(diffs) summary := ComputeArtifactLayerSummary(diffs)
for _, l := range summary.Layers { for _, l := range summary.Layers {
Debug(fmt.Sprintf("Diff %s -> %s: add %d (%d bytes), del %d (%d bytes), change %d (%d bytes)", ctx.Debug(fmt.Sprintf("Diff %s -> %s: add %d (%d bytes), del %d (%d bytes), change %d (%d bytes)",
l.FromImage, l.ToImage, l.FromImage, l.ToImage,
l.AddFiles, l.AddSizes, l.AddFiles, l.AddSizes,
l.DelFiles, l.DelSizes, l.DelFiles, l.DelSizes,

View File

@ -18,14 +18,11 @@ package backend_test
import ( import (
"testing" "testing"
. "github.com/mudler/luet/cmd/util"
. "github.com/onsi/ginkgo" . "github.com/onsi/ginkgo"
. "github.com/onsi/gomega" . "github.com/onsi/gomega"
) )
func TestSolver(t *testing.T) { func TestSolver(t *testing.T) {
RegisterFailHandler(Fail) RegisterFailHandler(Fail)
LoadConfig()
RunSpecs(t, "Backend Suite") RunSpecs(t, "Backend Suite")
} }

View File

@ -18,8 +18,7 @@ package backend
import ( import (
"os/exec" "os/exec"
"github.com/mudler/luet/pkg/config" "github.com/mudler/luet/pkg/api/core/types"
. "github.com/mudler/luet/pkg/logger"
"github.com/google/go-containerregistry/pkg/crane" "github.com/google/go-containerregistry/pkg/crane"
"github.com/pkg/errors" "github.com/pkg/errors"
@ -44,17 +43,17 @@ type Options struct {
BackendArgs []string BackendArgs []string
} }
func runCommand(cmd *exec.Cmd) error { func runCommand(ctx *types.Context, cmd *exec.Cmd) error {
output := "" output := ""
buffered := !config.LuetCfg.GetGeneral().ShowBuildOutput buffered := !ctx.Config.GetGeneral().ShowBuildOutput
writer := NewBackendWriter(buffered) writer := NewBackendWriter(buffered, ctx)
cmd.Stdout = writer cmd.Stdout = writer
cmd.Stderr = writer cmd.Stderr = writer
if buffered { if buffered {
Spinner(32) ctx.Spinner()
defer SpinnerStop() defer ctx.SpinnerStop()
} }
err := cmd.Start() err := cmd.Start()

View File

@ -23,64 +23,66 @@ import (
"path/filepath" "path/filepath"
"strings" "strings"
"github.com/mudler/luet/pkg/api/core/types"
bus "github.com/mudler/luet/pkg/bus" bus "github.com/mudler/luet/pkg/bus"
fileHelper "github.com/mudler/luet/pkg/helpers/file" fileHelper "github.com/mudler/luet/pkg/helpers/file"
capi "github.com/mudler/docker-companion/api" capi "github.com/mudler/docker-companion/api"
"github.com/mudler/luet/pkg/helpers" "github.com/mudler/luet/pkg/helpers"
. "github.com/mudler/luet/pkg/logger"
"github.com/pkg/errors" "github.com/pkg/errors"
) )
type SimpleDocker struct{} type SimpleDocker struct {
ctx *types.Context
}
func NewSimpleDockerBackend() *SimpleDocker { func NewSimpleDockerBackend(ctx *types.Context) *SimpleDocker {
return &SimpleDocker{} return &SimpleDocker{ctx: ctx}
} }
// TODO: Missing still: labels, and build args expansion // TODO: Missing still: labels, and build args expansion
func (*SimpleDocker) BuildImage(opts Options) error { func (s *SimpleDocker) BuildImage(opts Options) error {
name := opts.ImageName name := opts.ImageName
bus.Manager.Publish(bus.EventImagePreBuild, opts) bus.Manager.Publish(bus.EventImagePreBuild, opts)
buildarg := genBuildCommand(opts) buildarg := genBuildCommand(opts)
Info(":whale2: Building image " + name) s.ctx.Info(":whale2: Building image " + name)
cmd := exec.Command("docker", buildarg...) cmd := exec.Command("docker", buildarg...)
cmd.Dir = opts.SourcePath cmd.Dir = opts.SourcePath
err := runCommand(cmd) err := runCommand(s.ctx, cmd)
if err != nil { if err != nil {
return err return err
} }
Info(":whale: Building image " + name + " done") s.ctx.Info(":whale: Building image " + name + " done")
bus.Manager.Publish(bus.EventImagePostBuild, opts) bus.Manager.Publish(bus.EventImagePostBuild, opts)
return nil return nil
} }
func (*SimpleDocker) CopyImage(src, dst string) error { func (s *SimpleDocker) CopyImage(src, dst string) error {
Debug(":whale: Tagging image:", src, "->", dst) s.ctx.Debug(":whale: Tagging image:", src, "->", dst)
cmd := exec.Command("docker", "tag", src, dst) cmd := exec.Command("docker", "tag", src, dst)
out, err := cmd.CombinedOutput() out, err := cmd.CombinedOutput()
if err != nil { if err != nil {
return errors.Wrap(err, "Failed tagging image: "+string(out)) return errors.Wrap(err, "Failed tagging image: "+string(out))
} }
Info(":whale: Tagged image:", src, "->", dst) s.ctx.Info(":whale: Tagged image:", src, "->", dst)
return nil return nil
} }
func (*SimpleDocker) DownloadImage(opts Options) error { func (s *SimpleDocker) DownloadImage(opts Options) error {
name := opts.ImageName name := opts.ImageName
bus.Manager.Publish(bus.EventImagePrePull, opts) bus.Manager.Publish(bus.EventImagePrePull, opts)
buildarg := []string{"pull", name} buildarg := []string{"pull", name}
Debug(":whale: Downloading image " + name) s.ctx.Debug(":whale: Downloading image " + name)
Spinner(22) s.ctx.Spinner()
defer SpinnerStop() defer s.ctx.SpinnerStop()
cmd := exec.Command("docker", buildarg...) cmd := exec.Command("docker", buildarg...)
out, err := cmd.CombinedOutput() out, err := cmd.CombinedOutput()
@ -88,20 +90,20 @@ func (*SimpleDocker) DownloadImage(opts Options) error {
return errors.Wrap(err, "Failed pulling image: "+string(out)) return errors.Wrap(err, "Failed pulling image: "+string(out))
} }
Info(":whale: Downloaded image:", name) s.ctx.Info(":whale: Downloaded image:", name)
bus.Manager.Publish(bus.EventImagePostPull, opts) bus.Manager.Publish(bus.EventImagePostPull, opts)
return nil return nil
} }
func (*SimpleDocker) ImageExists(imagename string) bool { func (s *SimpleDocker) ImageExists(imagename string) bool {
buildarg := []string{"inspect", "--type=image", imagename} buildarg := []string{"inspect", "--type=image", imagename}
Debug(":whale: Checking existance of docker image: " + imagename) s.ctx.Debug(":whale: Checking existance of docker image: " + imagename)
cmd := exec.Command("docker", buildarg...) cmd := exec.Command("docker", buildarg...)
out, err := cmd.CombinedOutput() out, err := cmd.CombinedOutput()
if err != nil { if err != nil {
Debug("Image not present") s.ctx.Debug("Image not present")
Debug(string(out)) s.ctx.Debug(string(out))
return false return false
} }
return true return true
@ -111,31 +113,31 @@ func (*SimpleDocker) ImageAvailable(imagename string) bool {
return imageAvailable(imagename) return imageAvailable(imagename)
} }
func (*SimpleDocker) RemoveImage(opts Options) error { func (s *SimpleDocker) RemoveImage(opts Options) error {
name := opts.ImageName name := opts.ImageName
buildarg := []string{"rmi", name} buildarg := []string{"rmi", name}
out, err := exec.Command("docker", buildarg...).CombinedOutput() out, err := exec.Command("docker", buildarg...).CombinedOutput()
if err != nil { if err != nil {
return errors.Wrap(err, "Failed removing image: "+string(out)) return errors.Wrap(err, "Failed removing image: "+string(out))
} }
Info(":whale: Removed image:", name) s.ctx.Info(":whale: Removed image:", name)
//Info(string(out)) //Info(string(out))
return nil return nil
} }
func (*SimpleDocker) Push(opts Options) error { func (s *SimpleDocker) Push(opts Options) error {
name := opts.ImageName name := opts.ImageName
pusharg := []string{"push", name} pusharg := []string{"push", name}
bus.Manager.Publish(bus.EventImagePrePush, opts) bus.Manager.Publish(bus.EventImagePrePush, opts)
Spinner(22) s.ctx.Spinner()
defer SpinnerStop() defer s.ctx.SpinnerStop()
out, err := exec.Command("docker", pusharg...).CombinedOutput() out, err := exec.Command("docker", pusharg...).CombinedOutput()
if err != nil { if err != nil {
return errors.Wrap(err, "Failed pushing image: "+string(out)) return errors.Wrap(err, "Failed pushing image: "+string(out))
} }
Info(":whale: Pushed image:", name) s.ctx.Info(":whale: Pushed image:", name)
bus.Manager.Publish(bus.EventImagePostPush, opts) bus.Manager.Publish(bus.EventImagePostPush, opts)
//Info(string(out)) //Info(string(out))
@ -155,22 +157,22 @@ func (s *SimpleDocker) ImageDefinitionToTar(opts Options) error {
return nil return nil
} }
func (*SimpleDocker) ExportImage(opts Options) error { func (s *SimpleDocker) ExportImage(opts Options) error {
name := opts.ImageName name := opts.ImageName
path := opts.Destination path := opts.Destination
buildarg := []string{"save", name, "-o", path} buildarg := []string{"save", name, "-o", path}
Debug(":whale: Saving image " + name) s.ctx.Debug(":whale: Saving image " + name)
Spinner(22) s.ctx.Spinner()
defer SpinnerStop() defer s.ctx.SpinnerStop()
out, err := exec.Command("docker", buildarg...).CombinedOutput() out, err := exec.Command("docker", buildarg...).CombinedOutput()
if err != nil { if err != nil {
return errors.Wrap(err, "Failed exporting image: "+string(out)) return errors.Wrap(err, "Failed exporting image: "+string(out))
} }
Debug(":whale: Exported image:", name) s.ctx.Debug(":whale: Exported image:", name)
return nil return nil
} }
@ -196,15 +198,13 @@ func (b *SimpleDocker) ExtractRootfs(opts Options, keepPerms bool) error {
imageExport := filepath.Join(tempexport, "image.tar") imageExport := filepath.Join(tempexport, "image.tar")
Spinner(22) b.ctx.Spinner()
defer SpinnerStop() defer b.ctx.SpinnerStop()
if err := b.ExportImage(Options{ImageName: name, Destination: imageExport}); err != nil { if err := b.ExportImage(Options{ImageName: name, Destination: imageExport}); err != nil {
return errors.Wrap(err, "failed while extracting rootfs for "+name) return errors.Wrap(err, "failed while extracting rootfs for "+name)
} }
SpinnerStop()
src := imageExport src := imageExport
if src == "" && opts.ImageName != "" { if src == "" && opts.ImageName != "" {

View File

@ -16,6 +16,7 @@
package backend_test package backend_test
import ( import (
"github.com/mudler/luet/pkg/api/core/types"
"github.com/mudler/luet/pkg/api/core/types/artifact" "github.com/mudler/luet/pkg/api/core/types/artifact"
"github.com/mudler/luet/pkg/compiler" "github.com/mudler/luet/pkg/compiler"
. "github.com/mudler/luet/pkg/compiler" . "github.com/mudler/luet/pkg/compiler"
@ -35,6 +36,7 @@ import (
var _ = Describe("Docker backend", func() { var _ = Describe("Docker backend", func() {
Context("Simple Docker backend satisfies main interface functionalities", func() { Context("Simple Docker backend satisfies main interface functionalities", func() {
ctx := types.NewContext()
It("Builds and generate tars", func() { It("Builds and generate tars", func() {
generalRecipe := tree.NewGeneralRecipe(pkg.NewInMemoryDatabase(false)) generalRecipe := tree.NewGeneralRecipe(pkg.NewInMemoryDatabase(false))
@ -69,7 +71,7 @@ WORKDIR /luetbuild
ENV PACKAGE_NAME=enman ENV PACKAGE_NAME=enman
ENV PACKAGE_VERSION=1.4.0 ENV PACKAGE_VERSION=1.4.0
ENV PACKAGE_CATEGORY=app-admin`)) ENV PACKAGE_CATEGORY=app-admin`))
b := NewSimpleDockerBackend() b := NewSimpleDockerBackend(ctx)
opts := backend.Options{ opts := backend.Options{
ImageName: "luet/base", ImageName: "luet/base",
SourcePath: tmpdir, SourcePath: tmpdir,
@ -115,7 +117,7 @@ RUN echo bar > /test2`))
artifacts = append(artifacts, artifact.ArtifactNode{Name: "/test", Size: 4}) artifacts = append(artifacts, artifact.ArtifactNode{Name: "/test", Size: 4})
artifacts = append(artifacts, artifact.ArtifactNode{Name: "/test2", Size: 4}) artifacts = append(artifacts, artifact.ArtifactNode{Name: "/test2", Size: 4})
Expect(compiler.GenerateChanges(b, opts, opts2)).To(Equal( Expect(compiler.GenerateChanges(ctx, b, opts, opts2)).To(Equal(
[]artifact.ArtifactLayer{{ []artifact.ArtifactLayer{{
FromImage: "luet/base", FromImage: "luet/base",
ToImage: "test", ToImage: "test",
@ -137,7 +139,7 @@ RUN echo bar > /test2`))
}) })
It("Detects available images", func() { It("Detects available images", func() {
b := NewSimpleDockerBackend() b := NewSimpleDockerBackend(ctx)
Expect(b.ImageAvailable("quay.io/mocaccino/extra")).To(BeTrue()) Expect(b.ImageAvailable("quay.io/mocaccino/extra")).To(BeTrue())
Expect(b.ImageAvailable("ubuntu:20.10")).To(BeTrue()) Expect(b.ImageAvailable("ubuntu:20.10")).To(BeTrue())
Expect(b.ImageAvailable("igjo5ijgo25nho52")).To(BeFalse()) Expect(b.ImageAvailable("igjo5ijgo25nho52")).To(BeFalse())

View File

@ -20,64 +20,65 @@ import (
"os/exec" "os/exec"
"strings" "strings"
"github.com/mudler/luet/pkg/api/core/types"
bus "github.com/mudler/luet/pkg/bus" bus "github.com/mudler/luet/pkg/bus"
. "github.com/mudler/luet/pkg/logger"
"github.com/pkg/errors" "github.com/pkg/errors"
) )
type SimpleImg struct{} type SimpleImg struct {
ctx *types.Context
}
func NewSimpleImgBackend() *SimpleImg { func NewSimpleImgBackend(ctx *types.Context) *SimpleImg {
return &SimpleImg{} return &SimpleImg{ctx: ctx}
} }
// TODO: Missing still: labels, and build args expansion // TODO: Missing still: labels, and build args expansion
func (*SimpleImg) BuildImage(opts Options) error { func (s *SimpleImg) BuildImage(opts Options) error {
name := opts.ImageName name := opts.ImageName
bus.Manager.Publish(bus.EventImagePreBuild, opts) bus.Manager.Publish(bus.EventImagePreBuild, opts)
buildarg := genBuildCommand(opts) buildarg := genBuildCommand(opts)
Info(":tea: Building image " + name) s.ctx.Info(":tea: Building image " + name)
cmd := exec.Command("img", buildarg...) cmd := exec.Command("img", buildarg...)
cmd.Dir = opts.SourcePath cmd.Dir = opts.SourcePath
err := runCommand(cmd) err := runCommand(s.ctx, cmd)
if err != nil { if err != nil {
return err return err
} }
bus.Manager.Publish(bus.EventImagePostBuild, opts) bus.Manager.Publish(bus.EventImagePostBuild, opts)
Info(":tea: Building image " + name + " done") s.ctx.Info(":tea: Building image " + name + " done")
return nil return nil
} }
func (*SimpleImg) RemoveImage(opts Options) error { func (s *SimpleImg) RemoveImage(opts Options) error {
name := opts.ImageName name := opts.ImageName
buildarg := []string{"rm", name} buildarg := []string{"rm", name}
Spinner(22) s.ctx.Spinner()
defer SpinnerStop() defer s.ctx.SpinnerStop()
out, err := exec.Command("img", buildarg...).CombinedOutput() out, err := exec.Command("img", buildarg...).CombinedOutput()
if err != nil { if err != nil {
return errors.Wrap(err, "Failed removing image: "+string(out)) return errors.Wrap(err, "Failed removing image: "+string(out))
} }
Info(":tea: Image " + name + " removed") s.ctx.Info(":tea: Image " + name + " removed")
return nil return nil
} }
func (*SimpleImg) DownloadImage(opts Options) error { func (s *SimpleImg) DownloadImage(opts Options) error {
name := opts.ImageName name := opts.ImageName
bus.Manager.Publish(bus.EventImagePrePull, opts) bus.Manager.Publish(bus.EventImagePrePull, opts)
buildarg := []string{"pull", name} buildarg := []string{"pull", name}
Debug(":tea: Downloading image " + name) s.ctx.Debug(":tea: Downloading image " + name)
Spinner(22) s.ctx.Spinner()
defer SpinnerStop() defer s.ctx.SpinnerStop()
cmd := exec.Command("img", buildarg...) cmd := exec.Command("img", buildarg...)
out, err := cmd.CombinedOutput() out, err := cmd.CombinedOutput()
@ -85,27 +86,27 @@ func (*SimpleImg) DownloadImage(opts Options) error {
return errors.Wrap(err, "Failed downloading image: "+string(out)) return errors.Wrap(err, "Failed downloading image: "+string(out))
} }
Info(":tea: Image " + name + " downloaded") s.ctx.Info(":tea: Image " + name + " downloaded")
bus.Manager.Publish(bus.EventImagePostPull, opts) bus.Manager.Publish(bus.EventImagePostPull, opts)
return nil return nil
} }
func (*SimpleImg) CopyImage(src, dst string) error { func (s *SimpleImg) CopyImage(src, dst string) error {
Spinner(22) s.ctx.Spinner()
defer SpinnerStop() defer s.ctx.SpinnerStop()
Debug(":tea: Tagging image", src, dst) s.ctx.Debug(":tea: Tagging image", src, dst)
cmd := exec.Command("img", "tag", src, dst) cmd := exec.Command("img", "tag", src, dst)
out, err := cmd.CombinedOutput() out, err := cmd.CombinedOutput()
if err != nil { if err != nil {
return errors.Wrap(err, "Failed tagging image: "+string(out)) return errors.Wrap(err, "Failed tagging image: "+string(out))
} }
Info(":tea: Image " + dst + " tagged") s.ctx.Info(":tea: Image " + dst + " tagged")
return nil return nil
} }
func (*SimpleImg) ImageAvailable(imagename string) bool { func (s *SimpleImg) ImageAvailable(imagename string) bool {
return imageAvailable(imagename) return imageAvailable(imagename)
} }
@ -135,20 +136,20 @@ func (s *SimpleImg) ImageDefinitionToTar(opts Options) error {
return nil return nil
} }
func (*SimpleImg) ExportImage(opts Options) error { func (s *SimpleImg) ExportImage(opts Options) error {
name := opts.ImageName name := opts.ImageName
path := opts.Destination path := opts.Destination
buildarg := []string{"save", "-o", path, name} buildarg := []string{"save", "-o", path, name}
Debug(":tea: Saving image " + name) s.ctx.Debug(":tea: Saving image " + name)
Spinner(22) s.ctx.Spinner()
defer SpinnerStop() defer s.ctx.SpinnerStop()
out, err := exec.Command("img", buildarg...).CombinedOutput() out, err := exec.Command("img", buildarg...).CombinedOutput()
if err != nil { if err != nil {
return errors.Wrap(err, "Failed exporting image: "+string(out)) return errors.Wrap(err, "Failed exporting image: "+string(out))
} }
Info(":tea: Image " + name + " saved") s.ctx.Info(":tea: Image " + name + " saved")
return nil return nil
} }
@ -166,20 +167,20 @@ func (s *SimpleImg) ExtractRootfs(opts Options, keepPerms bool) error {
os.RemoveAll(path) os.RemoveAll(path)
buildarg := []string{"unpack", "-o", path, name} buildarg := []string{"unpack", "-o", path, name}
Debug(":tea: Extracting image " + name) s.ctx.Debug(":tea: Extracting image " + name)
Spinner(22) s.ctx.Spinner()
defer SpinnerStop() defer s.ctx.SpinnerStop()
out, err := exec.Command("img", buildarg...).CombinedOutput() out, err := exec.Command("img", buildarg...).CombinedOutput()
if err != nil { if err != nil {
return errors.Wrap(err, "Failed extracting image: "+string(out)) return errors.Wrap(err, "Failed extracting image: "+string(out))
} }
Debug(":tea: Image " + name + " extracted") s.ctx.Debug(":tea: Image " + name + " extracted")
return nil return nil
} }
func (*SimpleImg) Push(opts Options) error { func (s *SimpleImg) Push(opts Options) error {
name := opts.ImageName name := opts.ImageName
bus.Manager.Publish(bus.EventImagePrePush, opts) bus.Manager.Publish(bus.EventImagePrePush, opts)
@ -188,9 +189,9 @@ func (*SimpleImg) Push(opts Options) error {
if err != nil { if err != nil {
return errors.Wrap(err, "Failed pushing image: "+string(out)) return errors.Wrap(err, "Failed pushing image: "+string(out))
} }
Info(":tea: Pushed image:", name) s.ctx.Info(":tea: Pushed image:", name)
bus.Manager.Publish(bus.EventImagePostPush, opts) bus.Manager.Publish(bus.EventImagePostPush, opts)
//Info(string(out)) //s.ctx.Info(string(out))
return nil return nil
} }

View File

@ -19,18 +19,20 @@ package backend
import ( import (
"bytes" "bytes"
. "github.com/mudler/luet/pkg/logger" "github.com/mudler/luet/pkg/api/core/types"
) )
type BackendWriter struct { type BackendWriter struct {
BufferedOutput bool BufferedOutput bool
Buffer *bytes.Buffer Buffer *bytes.Buffer
ctx *types.Context
} }
func NewBackendWriter(buffered bool) *BackendWriter { func NewBackendWriter(buffered bool, ctx *types.Context) *BackendWriter {
return &BackendWriter{ return &BackendWriter{
BufferedOutput: buffered, BufferedOutput: buffered,
Buffer: &bytes.Buffer{}, Buffer: &bytes.Buffer{},
ctx: ctx,
} }
} }
@ -39,7 +41,7 @@ func (b *BackendWriter) Write(p []byte) (int, error) {
return b.Buffer.Write(p) return b.Buffer.Write(p)
} }
Msg("info", false, false, (string(p))) b.ctx.Msg("info", false, (string(p)))
return len(p), nil return len(p), nil
} }

View File

@ -16,6 +16,7 @@
package compiler_test package compiler_test
import ( import (
"github.com/mudler/luet/pkg/api/core/types"
. "github.com/mudler/luet/pkg/compiler" . "github.com/mudler/luet/pkg/compiler"
. "github.com/mudler/luet/pkg/compiler/backend" . "github.com/mudler/luet/pkg/compiler/backend"
@ -25,9 +26,9 @@ import (
var _ = Describe("Docker image diffs", func() { var _ = Describe("Docker image diffs", func() {
var b CompilerBackend var b CompilerBackend
ctx := types.NewContext()
BeforeEach(func() { BeforeEach(func() {
b = NewSimpleDockerBackend() b = NewSimpleDockerBackend(ctx)
}) })
Context("Generate diffs from docker images", func() { Context("Generate diffs from docker images", func() {
@ -38,7 +39,7 @@ var _ = Describe("Docker image diffs", func() {
err := b.DownloadImage(opts) err := b.DownloadImage(opts)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
layers, err := GenerateChanges(b, opts, opts) layers, err := GenerateChanges(ctx, b, opts, opts)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
Expect(len(layers)).To(Equal(1)) Expect(len(layers)).To(Equal(1))
Expect(len(layers[0].Diffs.Additions)).To(Equal(0)) Expect(len(layers[0].Diffs.Additions)).To(Equal(0))
@ -56,7 +57,7 @@ var _ = Describe("Docker image diffs", func() {
}) })
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
layers, err := GenerateChanges(b, Options{ layers, err := GenerateChanges(ctx, b, Options{
ImageName: "quay.io/mocaccino/micro", ImageName: "quay.io/mocaccino/micro",
}, Options{ }, Options{
ImageName: "quay.io/mocaccino/extra", ImageName: "quay.io/mocaccino/extra",

View File

@ -29,6 +29,7 @@ import (
"sync" "sync"
"time" "time"
"github.com/mudler/luet/pkg/api/core/types"
artifact "github.com/mudler/luet/pkg/api/core/types/artifact" artifact "github.com/mudler/luet/pkg/api/core/types/artifact"
bus "github.com/mudler/luet/pkg/bus" bus "github.com/mudler/luet/pkg/bus"
"github.com/mudler/luet/pkg/compiler/backend" "github.com/mudler/luet/pkg/compiler/backend"
@ -36,7 +37,6 @@ import (
compilerspec "github.com/mudler/luet/pkg/compiler/types/spec" compilerspec "github.com/mudler/luet/pkg/compiler/types/spec"
"github.com/mudler/luet/pkg/helpers" "github.com/mudler/luet/pkg/helpers"
fileHelper "github.com/mudler/luet/pkg/helpers/file" fileHelper "github.com/mudler/luet/pkg/helpers/file"
. "github.com/mudler/luet/pkg/logger"
pkg "github.com/mudler/luet/pkg/package" pkg "github.com/mudler/luet/pkg/package"
"github.com/mudler/luet/pkg/solver" "github.com/mudler/luet/pkg/solver"
@ -80,12 +80,12 @@ func NewLuetCompiler(backend CompilerBackend, db pkg.PackageDatabase, compilerOp
// The CompilerRecipe will gives us a tree with only build deps listed. // The CompilerRecipe will gives us a tree with only build deps listed.
c := NewCompiler(compilerOpts...) c := NewCompiler(compilerOpts...)
if c.Options.Context == nil {
c.Options.Context = types.NewContext()
}
// c.Options.BackendType // c.Options.BackendType
c.Backend = backend c.Backend = backend
c.Database = db c.Database = db
// c.CompilerRecipe = &tree.CompilerRecipe{
// Recipe: tree.Recipe{Database: db},
// }
return c return c
} }
@ -112,7 +112,7 @@ func (cs *LuetCompiler) CompileWithReverseDeps(keepPermissions bool, ps *compile
return artifacts, err return artifacts, err
} }
Info(":ant: Resolving reverse dependencies") cs.Options.Context.Info(":ant: Resolving reverse dependencies")
toCompile := compilerspec.NewLuetCompilationspecs() toCompile := compilerspec.NewLuetCompilationspecs()
for _, a := range artifacts { for _, a := range artifacts {
@ -130,7 +130,7 @@ func (cs *LuetCompiler) CompileWithReverseDeps(keepPermissions bool, ps *compile
uniques := toCompile.Unique().Remove(ps) uniques := toCompile.Unique().Remove(ps)
for _, u := range uniques.All() { for _, u := range uniques.All() {
Info(" :arrow_right_hook:", u.GetPackage().GetName(), ":leaves:", u.GetPackage().GetVersion(), "(", u.GetPackage().GetCategory(), ")") cs.Options.Context.Info(" :arrow_right_hook:", u.GetPackage().GetName(), ":leaves:", u.GetPackage().GetVersion(), "(", u.GetPackage().GetCategory(), ")")
} }
artifacts2, err := cs.CompileParallel(keepPermissions, uniques) artifacts2, err := cs.CompileParallel(keepPermissions, uniques)
@ -202,9 +202,9 @@ func (cs *LuetCompiler) stripFromRootfs(includes []string, rootfs string, includ
if include && !match || !include && match { if include && !match || !include && match {
toRemove = append(toRemove, currentpath) toRemove = append(toRemove, currentpath)
Debug(":scissors: Removing file", currentpath) cs.Options.Context.Debug(":scissors: Removing file", currentpath)
} else { } else {
Debug(":sun: Matched file", currentpath) cs.Options.Context.Debug(":sun: Matched file", currentpath)
} }
return nil return nil
@ -218,7 +218,7 @@ func (cs *LuetCompiler) stripFromRootfs(includes []string, rootfs string, includ
for _, s := range toRemove { for _, s := range toRemove {
e := os.RemoveAll(s) e := os.RemoveAll(s)
if e != nil { if e != nil {
Warning("Failed removing", s, e.Error()) cs.Options.Context.Warning("Failed removing", s, e.Error())
return e return e
} }
} }
@ -240,7 +240,7 @@ func (cs *LuetCompiler) unpackFs(concurrency int, keepPermissions bool, p *compi
} }
if p.GetPackageDir() != "" { if p.GetPackageDir() != "" {
Info(":tophat: Packing from output dir", p.GetPackageDir()) cs.Options.Context.Info(":tophat: Packing from output dir", p.GetPackageDir())
rootfs = filepath.Join(rootfs, p.GetPackageDir()) rootfs = filepath.Join(rootfs, p.GetPackageDir())
} }
@ -279,18 +279,18 @@ func (cs *LuetCompiler) unpackDelta(concurrency int, keepPermissions bool, p *co
} }
} }
Info(pkgTag, ":hammer: Generating delta") cs.Options.Context.Info(pkgTag, ":hammer: Generating delta")
diffs, err := GenerateChanges(cs.Backend, builderOpts, runnerOpts) diffs, err := GenerateChanges(cs.Options.Context, cs.Backend, builderOpts, runnerOpts)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "Could not generate changes from layers") return nil, errors.Wrap(err, "Could not generate changes from layers")
} }
Debug("Extracting image to grab files from delta") cs.Options.Context.Debug("Extracting image to grab files from delta")
if err := cs.Backend.ExtractRootfs(backend.Options{ if err := cs.Backend.ExtractRootfs(backend.Options{
ImageName: runnerOpts.ImageName, Destination: rootfs}, keepPermissions); err != nil { ImageName: runnerOpts.ImageName, Destination: rootfs}, keepPermissions); err != nil {
return nil, errors.Wrap(err, "Could not extract rootfs") return nil, errors.Wrap(err, "Could not extract rootfs")
} }
artifact, err := artifact.ExtractArtifactFromDelta(rootfs, p.Rel(p.GetPackage().GetFingerPrint()+".package.tar"), diffs, concurrency, keepPermissions, p.GetIncludes(), p.GetExcludes(), cs.Options.CompressionType) artifact, err := artifact.ExtractArtifactFromDelta(cs.Options.Context, rootfs, p.Rel(p.GetPackage().GetFingerPrint()+".package.tar"), diffs, concurrency, keepPermissions, p.GetIncludes(), p.GetExcludes(), cs.Options.CompressionType)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "Could not generate deltas") return nil, errors.Wrap(err, "Could not generate deltas")
} }
@ -335,7 +335,7 @@ func (cs *LuetCompiler) buildPackageImage(image, buildertaggedImage, packageImag
if len(p.GetRetrieve()) > 0 { if len(p.GetRetrieve()) > 0 {
err := p.CopyRetrieves(buildDir) err := p.CopyRetrieves(buildDir)
if err != nil { if err != nil {
Warning("Failed copying retrieves", err.Error()) cs.Options.Context.Warning("Failed copying retrieves", err.Error())
} }
} }
@ -381,8 +381,8 @@ func (cs *LuetCompiler) buildPackageImage(image, buildertaggedImage, packageImag
if err == nil { if err == nil {
buildImage = false buildImage = false
} else { } else {
Warning("Failed to download '" + opts.ImageName + "'. Will keep going and build the image unless you use --fatal") cs.Options.Context.Warning("Failed to download '" + opts.ImageName + "'. Will keep going and build the image unless you use --fatal")
Warning(err.Error()) cs.Options.Context.Warning(err.Error())
} }
} }
if buildImage { if buildImage {
@ -399,7 +399,7 @@ func (cs *LuetCompiler) buildPackageImage(image, buildertaggedImage, packageImag
} }
// SKIPBUILD // SKIPBUILD
// if len(p.GetPreBuildSteps()) != 0 { // if len(p.GetPreBuildSteps()) != 0 {
Info(pkgTag, ":whale: Generating 'builder' image from", image, "as", buildertaggedImage, "with prelude steps") cs.Options.Context.Info(pkgTag, ":whale: Generating 'builder' image from", image, "as", buildertaggedImage, "with prelude steps")
if err := buildAndPush(builderOpts); err != nil { if err := buildAndPush(builderOpts); err != nil {
return builderOpts, runnerOpts, errors.Wrapf(err, "Could not push image: %s %s", image, builderOpts.DockerFileName) return builderOpts, runnerOpts, errors.Wrapf(err, "Could not push image: %s %s", image, builderOpts.DockerFileName)
} }
@ -407,7 +407,7 @@ func (cs *LuetCompiler) buildPackageImage(image, buildertaggedImage, packageImag
// Even if we might not have any steps to build, we do that so we can tag the image used in this moment and use that to cache it in a registry, or in the system. // Even if we might not have any steps to build, we do that so we can tag the image used in this moment and use that to cache it in a registry, or in the system.
// acting as a docker tag. // acting as a docker tag.
Info(pkgTag, ":whale: Generating 'package' image from", buildertaggedImage, "as", packageImage, "with build steps") cs.Options.Context.Info(pkgTag, ":whale: Generating 'package' image from", buildertaggedImage, "as", packageImage, "with build steps")
if err := buildAndPush(runnerOpts); err != nil { if err := buildAndPush(runnerOpts); err != nil {
return builderOpts, runnerOpts, errors.Wrapf(err, "Could not push image: %s %s", image, runnerOpts.DockerFileName) return builderOpts, runnerOpts, errors.Wrapf(err, "Could not push image: %s %s", image, runnerOpts.DockerFileName)
} }
@ -422,7 +422,7 @@ func (cs *LuetCompiler) genArtifact(p *compilerspec.LuetCompilationSpec, builder
var rootfs string var rootfs string
var err error var err error
pkgTag := ":package: " + p.GetPackage().HumanReadableString() pkgTag := ":package: " + p.GetPackage().HumanReadableString()
Debug(pkgTag, "Generating artifact") cs.Options.Context.Debug(pkgTag, "Generating artifact")
// We can't generate delta in this case. It implies the package is a virtual, and nothing has to be done really // We can't generate delta in this case. It implies the package is a virtual, and nothing has to be done really
if p.EmptyPackage() { if p.EmptyPackage() {
fakePackage := p.Rel(p.GetPackage().GetFingerPrint() + ".package.tar") fakePackage := p.Rel(p.GetPackage().GetFingerPrint() + ".package.tar")
@ -447,7 +447,7 @@ func (cs *LuetCompiler) genArtifact(p *compilerspec.LuetCompilationSpec, builder
if err != nil { if err != nil {
return a, errors.Wrap(err, "Failed while writing metadata file") return a, errors.Wrap(err, "Failed while writing metadata file")
} }
Info(pkgTag, " :white_check_mark: done (empty virtual package)") cs.Options.Context.Info(pkgTag, " :white_check_mark: done (empty virtual package)")
return a, nil return a, nil
} }
@ -477,7 +477,7 @@ func (cs *LuetCompiler) genArtifact(p *compilerspec.LuetCompilationSpec, builder
if err != nil { if err != nil {
return a, errors.Wrap(err, "Failed while writing metadata file") return a, errors.Wrap(err, "Failed while writing metadata file")
} }
Info(pkgTag, " :white_check_mark: Done") cs.Options.Context.Info(pkgTag, " :white_check_mark: Done")
return a, nil return a, nil
} }
@ -486,12 +486,12 @@ func (cs *LuetCompiler) waitForImages(images []string) {
if cs.Options.PullFirst && cs.Options.Wait { if cs.Options.PullFirst && cs.Options.Wait {
available, _ := oneOfImagesAvailable(images, cs.Backend) available, _ := oneOfImagesAvailable(images, cs.Backend)
if !available { if !available {
Info(fmt.Sprintf("Waiting for image %s to be available... :zzz:", images)) cs.Options.Context.Info(fmt.Sprintf("Waiting for image %s to be available... :zzz:", images))
Spinner(32) cs.Options.Context.Spinner()
defer SpinnerStop() defer cs.Options.Context.SpinnerStop()
for !available { for !available {
available, _ = oneOfImagesAvailable(images, cs.Backend) available, _ = oneOfImagesAvailable(images, cs.Backend)
Info(fmt.Sprintf("Image %s not available yet, sleeping", images)) cs.Options.Context.Info(fmt.Sprintf("Image %s not available yet, sleeping", images))
time.Sleep(5 * time.Second) time.Sleep(5 * time.Second)
} }
} }
@ -517,7 +517,7 @@ func oneOfImagesAvailable(images []string, b CompilerBackend) (bool, string) {
func (cs *LuetCompiler) findImageHash(imageHash string, p *compilerspec.LuetCompilationSpec) string { func (cs *LuetCompiler) findImageHash(imageHash string, p *compilerspec.LuetCompilationSpec) string {
var resolvedImage string var resolvedImage string
Debug("Resolving image hash for", p.Package.HumanReadableString(), "hash", imageHash, "Pull repositories", p.BuildOptions.PullImageRepository) cs.Options.Context.Debug("Resolving image hash for", p.Package.HumanReadableString(), "hash", imageHash, "Pull repositories", p.BuildOptions.PullImageRepository)
toChecklist := append([]string{fmt.Sprintf("%s:%s", cs.Options.PushImageRepository, imageHash)}, toChecklist := append([]string{fmt.Sprintf("%s:%s", cs.Options.PushImageRepository, imageHash)},
genImageList(p.BuildOptions.PullImageRepository, imageHash)...) genImageList(p.BuildOptions.PullImageRepository, imageHash)...)
if exists, which := oneOfImagesExists(toChecklist, cs.Backend); exists { if exists, which := oneOfImagesExists(toChecklist, cs.Backend); exists {
@ -558,20 +558,20 @@ func LoadArtifactFromYaml(spec *compilerspec.LuetCompilationSpec) (*artifact.Pac
func (cs *LuetCompiler) getImageArtifact(hash string, p *compilerspec.LuetCompilationSpec) (*artifact.PackageArtifact, error) { func (cs *LuetCompiler) getImageArtifact(hash string, p *compilerspec.LuetCompilationSpec) (*artifact.PackageArtifact, error) {
// we check if there is an available image with the given hash and // we check if there is an available image with the given hash and
// we return a full artifact if can be loaded locally. // we return a full artifact if can be loaded locally.
Debug("Get image artifact for", p.Package.HumanReadableString(), "hash", hash, "Pull repositories", p.BuildOptions.PullImageRepository) cs.Options.Context.Debug("Get image artifact for", p.Package.HumanReadableString(), "hash", hash, "Pull repositories", p.BuildOptions.PullImageRepository)
toChecklist := append([]string{fmt.Sprintf("%s:%s", cs.Options.PushImageRepository, hash)}, toChecklist := append([]string{fmt.Sprintf("%s:%s", cs.Options.PushImageRepository, hash)},
genImageList(p.BuildOptions.PullImageRepository, hash)...) genImageList(p.BuildOptions.PullImageRepository, hash)...)
exists, _ := oneOfImagesExists(toChecklist, cs.Backend) exists, _ := oneOfImagesExists(toChecklist, cs.Backend)
if art, err := LoadArtifactFromYaml(p); err == nil && exists { // If YAML is correctly loaded, and both images exists, no reason to rebuild. if art, err := LoadArtifactFromYaml(p); err == nil && exists { // If YAML is correctly loaded, and both images exists, no reason to rebuild.
Debug("Package reloaded from YAML. Skipping build") cs.Options.Context.Debug("Package reloaded from YAML. Skipping build")
return art, nil return art, nil
} }
cs.waitForImages(toChecklist) cs.waitForImages(toChecklist)
available, _ := oneOfImagesAvailable(toChecklist, cs.Backend) available, _ := oneOfImagesAvailable(toChecklist, cs.Backend)
if exists || (cs.Options.PullFirst && available) { if exists || (cs.Options.PullFirst && available) {
Debug("Image available, returning empty artifact") cs.Options.Context.Debug("Image available, returning empty artifact")
return &artifact.PackageArtifact{}, nil return &artifact.PackageArtifact{}, nil
} }
@ -610,17 +610,17 @@ func (cs *LuetCompiler) compileWithImage(image, builderHash string, packageTagHa
// if buildertaggedImage == "" { // if buildertaggedImage == "" {
// buildertaggedImage = fmt.Sprintf("%s:%s", cs.Options.PushImageRepository, buildertaggedImage) // buildertaggedImage = fmt.Sprintf("%s:%s", cs.Options.PushImageRepository, buildertaggedImage)
// generated = true // generated = true
// // Debug(pkgTag, "Creating intermediary image", buildertaggedImage, "from", image) // // cs.Options.Context.Debug(pkgTag, "Creating intermediary image", buildertaggedImage, "from", image)
// } // }
if cs.Options.PullFirst && !cs.Options.Rebuild { if cs.Options.PullFirst && !cs.Options.Rebuild {
Debug("Checking if an image is already available") cs.Options.Context.Debug("Checking if an image is already available")
// FIXUP here. If packageimage hash exists and pull is true, generate package // FIXUP here. If packageimage hash exists and pull is true, generate package
resolved := cs.resolveExistingImageHash(packageTagHash, p) resolved := cs.resolveExistingImageHash(packageTagHash, p)
Debug("Resolved: " + resolved) cs.Options.Context.Debug("Resolved: " + resolved)
Debug("Expected remote: " + resolved) cs.Options.Context.Debug("Expected remote: " + resolved)
Debug("Package image: " + packageImage) cs.Options.Context.Debug("Package image: " + packageImage)
Debug("Resolved builder image: " + builderResolved) cs.Options.Context.Debug("Resolved builder image: " + builderResolved)
// a remote image is there already // a remote image is there already
remoteImageAvailable := resolved != packageImage && remoteBuildertaggedImage != builderResolved remoteImageAvailable := resolved != packageImage && remoteBuildertaggedImage != builderResolved
@ -629,13 +629,13 @@ func (cs *LuetCompiler) compileWithImage(image, builderHash string, packageTagHa
switch { switch {
case remoteImageAvailable: case remoteImageAvailable:
Debug("Images available remotely for", p.Package.HumanReadableString(), "generating artifact from remote images:", resolved) cs.Options.Context.Debug("Images available remotely for", p.Package.HumanReadableString(), "generating artifact from remote images:", resolved)
return cs.genArtifact(p, backend.Options{ImageName: builderResolved}, backend.Options{ImageName: resolved}, concurrency, keepPermissions) return cs.genArtifact(p, backend.Options{ImageName: builderResolved}, backend.Options{ImageName: resolved}, concurrency, keepPermissions)
case localImageAvailable: case localImageAvailable:
Debug("Images locally available for", p.Package.HumanReadableString(), "generating artifact from image:", resolved) cs.Options.Context.Debug("Images locally available for", p.Package.HumanReadableString(), "generating artifact from image:", resolved)
return cs.genArtifact(p, backend.Options{ImageName: remoteBuildertaggedImage}, backend.Options{ImageName: packageImage}, concurrency, keepPermissions) return cs.genArtifact(p, backend.Options{ImageName: remoteBuildertaggedImage}, backend.Options{ImageName: packageImage}, concurrency, keepPermissions)
default: default:
Debug("Images not available for", p.Package.HumanReadableString()) cs.Options.Context.Debug("Images not available for", p.Package.HumanReadableString())
} }
} }
@ -649,10 +649,10 @@ func (cs *LuetCompiler) compileWithImage(image, builderHash string, packageTagHa
defer func() { defer func() {
// We keep them around, so to not reload them from the tar (which should be the "correct way") and we automatically share the same layers // We keep them around, so to not reload them from the tar (which should be the "correct way") and we automatically share the same layers
if err := cs.Backend.RemoveImage(builderOpts); err != nil { if err := cs.Backend.RemoveImage(builderOpts); err != nil {
Warning("Could not remove image ", builderOpts.ImageName) cs.Options.Context.Warning("Could not remove image ", builderOpts.ImageName)
} }
if err := cs.Backend.RemoveImage(runnerOpts); err != nil { if err := cs.Backend.RemoveImage(runnerOpts); err != nil {
Warning("Could not remove image ", runnerOpts.ImageName) cs.Options.Context.Warning("Could not remove image ", runnerOpts.ImageName)
} }
}() }()
} }
@ -787,22 +787,22 @@ func genImageList(refs []string, hash string) []string {
} }
func (cs *LuetCompiler) inheritSpecBuildOptions(p *compilerspec.LuetCompilationSpec) { func (cs *LuetCompiler) inheritSpecBuildOptions(p *compilerspec.LuetCompilationSpec) {
Debug(p.GetPackage().HumanReadableString(), "Build options before inherit", p.BuildOptions) cs.Options.Context.Debug(p.GetPackage().HumanReadableString(), "Build options before inherit", p.BuildOptions)
// Append push repositories from buildpsec buildoptions as pull if found. // Append push repositories from buildpsec buildoptions as pull if found.
// This allows to resolve the hash automatically if we pulled the metadata from // This allows to resolve the hash automatically if we pulled the metadata from
// repositories that are advertizing their cache. // repositories that are advertizing their cache.
if len(p.BuildOptions.PushImageRepository) != 0 { if len(p.BuildOptions.PushImageRepository) != 0 {
p.BuildOptions.PullImageRepository = append(p.BuildOptions.PullImageRepository, p.BuildOptions.PushImageRepository) p.BuildOptions.PullImageRepository = append(p.BuildOptions.PullImageRepository, p.BuildOptions.PushImageRepository)
Debug("Inheriting pull repository from PushImageRepository buildoptions", p.BuildOptions.PullImageRepository) cs.Options.Context.Debug("Inheriting pull repository from PushImageRepository buildoptions", p.BuildOptions.PullImageRepository)
} }
if len(cs.Options.PullImageRepository) != 0 { if len(cs.Options.PullImageRepository) != 0 {
p.BuildOptions.PullImageRepository = append(p.BuildOptions.PullImageRepository, cs.Options.PullImageRepository...) p.BuildOptions.PullImageRepository = append(p.BuildOptions.PullImageRepository, cs.Options.PullImageRepository...)
Debug("Inheriting pull repository from PullImageRepository buildoptions", p.BuildOptions.PullImageRepository) cs.Options.Context.Debug("Inheriting pull repository from PullImageRepository buildoptions", p.BuildOptions.PullImageRepository)
} }
Debug(p.GetPackage().HumanReadableString(), "Build options after inherit", p.BuildOptions) cs.Options.Context.Debug(p.GetPackage().HumanReadableString(), "Build options after inherit", p.BuildOptions)
} }
func (cs *LuetCompiler) getSpecHash(pkgs pkg.DefaultPackages, salt string) (string, error) { func (cs *LuetCompiler) getSpecHash(pkgs pkg.DefaultPackages, salt string) (string, error) {
@ -831,7 +831,7 @@ func (cs *LuetCompiler) resolveFinalImages(concurrency int, keepPermissions bool
var fromPackages pkg.DefaultPackages var fromPackages pkg.DefaultPackages
if p.RequiresFinalImages { if p.RequiresFinalImages {
Info(joinTag, "Generating a parent image from final packages") cs.Options.Context.Info(joinTag, "Generating a parent image from final packages")
fromPackages = p.Package.GetRequires() fromPackages = p.Package.GetRequires()
} else { } else {
// No source image to resolve // No source image to resolve
@ -844,15 +844,15 @@ func (cs *LuetCompiler) resolveFinalImages(concurrency int, keepPermissions bool
return errors.Wrap(err, "could not generate image hash") return errors.Wrap(err, "could not generate image hash")
} }
Info(joinTag, "Searching existing image with hash", overallFp) cs.Options.Context.Info(joinTag, "Searching existing image with hash", overallFp)
image := cs.findImageHash(overallFp, p) image := cs.findImageHash(overallFp, p)
if image != "" { if image != "" {
Info("Image already found", image) cs.Options.Context.Info("Image already found", image)
p.SetImage(image) p.SetImage(image)
return nil return nil
} }
Info(joinTag, "Image not found. Generating image join with hash ", overallFp) cs.Options.Context.Info(joinTag, "Image not found. Generating image join with hash ", overallFp)
// Make sure there is an output path // Make sure there is an output path
if err := os.MkdirAll(p.GetOutputPath(), os.ModePerm); err != nil { if err := os.MkdirAll(p.GetOutputPath(), os.ModePerm); err != nil {
@ -867,7 +867,7 @@ func (cs *LuetCompiler) resolveFinalImages(concurrency int, keepPermissions bool
defer os.RemoveAll(joinDir) // clean up defer os.RemoveAll(joinDir) // clean up
for _, p := range fromPackages { for _, p := range fromPackages {
Info(joinTag, ":arrow_right_hook:", p.HumanReadableString(), ":leaves:") cs.Options.Context.Info(joinTag, ":arrow_right_hook:", p.HumanReadableString(), ":leaves:")
} }
current := 0 current := 0
@ -876,7 +876,7 @@ func (cs *LuetCompiler) resolveFinalImages(concurrency int, keepPermissions bool
if c != nil && c.Name != "" && c.Version != "" { if c != nil && c.Name != "" && c.Version != "" {
joinTag2 := fmt.Sprintf("%s %d/%d ⤑ :hammer: build %s", joinTag, current, len(p.Package.GetRequires()), c.HumanReadableString()) joinTag2 := fmt.Sprintf("%s %d/%d ⤑ :hammer: build %s", joinTag, current, len(p.Package.GetRequires()), c.HumanReadableString())
Info(joinTag2, "compilation starts") cs.Options.Context.Info(joinTag2, "compilation starts")
spec, err := cs.FromPackage(c) spec, err := cs.FromPackage(c)
if err != nil { if err != nil {
return errors.Wrap(err, "while generating images to join from") return errors.Wrap(err, "while generating images to join from")
@ -891,11 +891,11 @@ func (cs *LuetCompiler) resolveFinalImages(concurrency int, keepPermissions bool
return errors.Wrap(err, "failed building join image") return errors.Wrap(err, "failed building join image")
} }
err = artifact.Unpack(joinDir, keepPermissions) err = artifact.Unpack(cs.Options.Context, joinDir, keepPermissions)
if err != nil { if err != nil {
return errors.Wrap(err, "failed building join image") return errors.Wrap(err, "failed building join image")
} }
Info(joinTag2, ":white_check_mark: Done") cs.Options.Context.Info(joinTag2, ":white_check_mark: Done")
} }
} }
@ -905,7 +905,7 @@ func (cs *LuetCompiler) resolveFinalImages(concurrency int, keepPermissions bool
} }
defer os.RemoveAll(joinDir) // clean up defer os.RemoveAll(joinDir) // clean up
Info(joinTag, ":droplet: generating artifact for source image of", p.GetPackage().HumanReadableString()) cs.Options.Context.Info(joinTag, ":droplet: generating artifact for source image of", p.GetPackage().HumanReadableString())
// After unpack, create a new artifact and a new final image from it. // After unpack, create a new artifact and a new final image from it.
// no need to compress, as we are going to toss it away. // no need to compress, as we are going to toss it away.
@ -915,18 +915,18 @@ func (cs *LuetCompiler) resolveFinalImages(concurrency int, keepPermissions bool
} }
joinImageName := fmt.Sprintf("%s:%s", cs.Options.PushImageRepository, overallFp) joinImageName := fmt.Sprintf("%s:%s", cs.Options.PushImageRepository, overallFp)
Info(joinTag, ":droplet: generating image from artifact", joinImageName) cs.Options.Context.Info(joinTag, ":droplet: generating image from artifact", joinImageName)
opts, err := a.GenerateFinalImage(joinImageName, cs.Backend, keepPermissions) opts, err := a.GenerateFinalImage(cs.Options.Context, joinImageName, cs.Backend, keepPermissions)
if err != nil { if err != nil {
return errors.Wrap(err, "could not create final image") return errors.Wrap(err, "could not create final image")
} }
if cs.Options.Push { if cs.Options.Push {
Info(joinTag, ":droplet: pushing image from artifact", joinImageName) cs.Options.Context.Info(joinTag, ":droplet: pushing image from artifact", joinImageName)
if err = cs.Backend.Push(opts); err != nil { if err = cs.Backend.Push(opts); err != nil {
return errors.Wrapf(err, "Could not push image: %s %s", image, opts.DockerFileName) return errors.Wrapf(err, "Could not push image: %s %s", image, opts.DockerFileName)
} }
} }
Info(joinTag, ":droplet: Consuming image", joinImageName) cs.Options.Context.Info(joinTag, ":droplet: Consuming image", joinImageName)
p.SetImage(joinImageName) p.SetImage(joinImageName)
return nil return nil
} }
@ -936,7 +936,7 @@ func (cs *LuetCompiler) resolveMultiStageImages(concurrency int, keepPermissions
copyTag := ">:droplet: copy<" copyTag := ">:droplet: copy<"
if len(p.Copy) != 0 { if len(p.Copy) != 0 {
Info(copyTag, "Package has multi-stage copy, generating required images") cs.Options.Context.Info(copyTag, "Package has multi-stage copy, generating required images")
} }
current := 0 current := 0
@ -946,7 +946,7 @@ func (cs *LuetCompiler) resolveMultiStageImages(concurrency int, keepPermissions
if c.Package != nil && c.Package.Name != "" && c.Package.Version != "" { if c.Package != nil && c.Package.Name != "" && c.Package.Version != "" {
copyTag2 := fmt.Sprintf("%s %d/%d ⤑ :hammer: build %s", copyTag, current, len(p.Copy), c.Package.HumanReadableString()) copyTag2 := fmt.Sprintf("%s %d/%d ⤑ :hammer: build %s", copyTag, current, len(p.Copy), c.Package.HumanReadableString())
Info(copyTag2, "generating multi-stage images for", c.Package.HumanReadableString()) cs.Options.Context.Info(copyTag2, "generating multi-stage images for", c.Package.HumanReadableString())
spec, err := cs.FromPackage(c.Package) spec, err := cs.FromPackage(c.Package)
if err != nil { if err != nil {
return errors.Wrap(err, "while generating images to copy from") return errors.Wrap(err, "while generating images to copy from")
@ -965,7 +965,7 @@ func (cs *LuetCompiler) resolveMultiStageImages(concurrency int, keepPermissions
Source: c.Source, Source: c.Source,
Destination: c.Destination, Destination: c.Destination,
}) })
Info(copyTag2, ":white_check_mark: Done") cs.Options.Context.Info(copyTag2, ":white_check_mark: Done")
} else { } else {
resolvedCopyFields = append(resolvedCopyFields, c) resolvedCopyFields = append(resolvedCopyFields, c)
} }
@ -975,7 +975,7 @@ func (cs *LuetCompiler) resolveMultiStageImages(concurrency int, keepPermissions
} }
func (cs *LuetCompiler) compile(concurrency int, keepPermissions bool, generateFinalArtifact *bool, generateDependenciesFinalArtifact *bool, p *compilerspec.LuetCompilationSpec) (*artifact.PackageArtifact, error) { func (cs *LuetCompiler) compile(concurrency int, keepPermissions bool, generateFinalArtifact *bool, generateDependenciesFinalArtifact *bool, p *compilerspec.LuetCompilationSpec) (*artifact.PackageArtifact, error) {
Info(":package: Compiling", p.GetPackage().HumanReadableString(), ".... :coffee:") cs.Options.Context.Info(":package: Compiling", p.GetPackage().HumanReadableString(), ".... :coffee:")
//Before multistage : join - same as multistage, but keep artifacts, join them, create a new one and generate a final image. //Before multistage : join - same as multistage, but keep artifacts, join them, create a new one and generate a final image.
// When the image is there, use it as a source here, in place of GetImage(). // When the image is there, use it as a source here, in place of GetImage().
@ -987,7 +987,7 @@ func (cs *LuetCompiler) compile(concurrency int, keepPermissions bool, generateF
return nil, errors.Wrap(err, "while resolving multi-stage images") return nil, errors.Wrap(err, "while resolving multi-stage images")
} }
Debug(fmt.Sprintf("%s: has images %t, empty package: %t", p.GetPackage().HumanReadableString(), p.HasImageSource(), p.EmptyPackage())) cs.Options.Context.Debug(fmt.Sprintf("%s: has images %t, empty package: %t", p.GetPackage().HumanReadableString(), p.HasImageSource(), p.EmptyPackage()))
if !p.HasImageSource() && !p.EmptyPackage() { if !p.HasImageSource() && !p.EmptyPackage() {
return nil, return nil,
fmt.Errorf( fmt.Errorf(
@ -1056,22 +1056,22 @@ func (cs *LuetCompiler) compile(concurrency int, keepPermissions bool, generateF
buildTarget := !cs.Options.OnlyDeps buildTarget := !cs.Options.OnlyDeps
if buildDeps { if buildDeps {
Info(":deciduous_tree: Build dependencies for " + p.GetPackage().HumanReadableString()) cs.Options.Context.Info(":deciduous_tree: Build dependencies for " + p.GetPackage().HumanReadableString())
for _, assertion := range dependencies { //highly dependent on the order for _, assertion := range dependencies { //highly dependent on the order
depsN++ depsN++
Info(" :arrow_right_hook:", assertion.Package.HumanReadableString(), ":leaves:") cs.Options.Context.Info(" :arrow_right_hook:", assertion.Package.HumanReadableString(), ":leaves:")
} }
for _, assertion := range dependencies { //highly dependent on the order for _, assertion := range dependencies { //highly dependent on the order
currentN++ currentN++
pkgTag := fmt.Sprintf(":package: %d/%d %s ⤑ :hammer: build %s", currentN, depsN, p.GetPackage().HumanReadableString(), assertion.Package.HumanReadableString()) pkgTag := fmt.Sprintf(":package: %d/%d %s ⤑ :hammer: build %s", currentN, depsN, p.GetPackage().HumanReadableString(), assertion.Package.HumanReadableString())
Info(pkgTag, " starts") cs.Options.Context.Info(pkgTag, " starts")
compileSpec, err := cs.FromPackage(assertion.Package) compileSpec, err := cs.FromPackage(assertion.Package)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "Error while generating compilespec for "+assertion.Package.GetName()) return nil, errors.Wrap(err, "Error while generating compilespec for "+assertion.Package.GetName())
} }
compileSpec.BuildOptions.PullImageRepository = append(compileSpec.BuildOptions.PullImageRepository, p.BuildOptions.PullImageRepository...) compileSpec.BuildOptions.PullImageRepository = append(compileSpec.BuildOptions.PullImageRepository, p.BuildOptions.PullImageRepository...)
Debug("PullImage repos:", compileSpec.BuildOptions.PullImageRepository) cs.Options.Context.Debug("PullImage repos:", compileSpec.BuildOptions.PullImageRepository)
compileSpec.SetOutputPath(p.GetOutputPath()) compileSpec.SetOutputPath(p.GetOutputPath())
@ -1096,20 +1096,20 @@ func (cs *LuetCompiler) compile(concurrency int, keepPermissions bool, generateF
return nil, errors.Wrap(err, "failed looking for dependency in hashtree") return nil, errors.Wrap(err, "failed looking for dependency in hashtree")
} }
Debug(pkgTag, " :arrow_right_hook: :whale: Builder image from hash", assertion.Hash.BuildHash) cs.Options.Context.Debug(pkgTag, " :arrow_right_hook: :whale: Builder image from hash", assertion.Hash.BuildHash)
Debug(pkgTag, " :arrow_right_hook: :whale: Package image from hash", assertion.Hash.PackageHash) cs.Options.Context.Debug(pkgTag, " :arrow_right_hook: :whale: Package image from hash", assertion.Hash.PackageHash)
var sourceImage string var sourceImage string
if compileSpec.GetImage() != "" { if compileSpec.GetImage() != "" {
Debug(pkgTag, " :wrench: Compiling "+compileSpec.GetPackage().HumanReadableString()+" from image") cs.Options.Context.Debug(pkgTag, " :wrench: Compiling "+compileSpec.GetPackage().HumanReadableString()+" from image")
sourceImage = compileSpec.GetImage() sourceImage = compileSpec.GetImage()
} else { } else {
// for the source instead, pick an image and a buildertaggedImage from hashes if they exists. // for the source instead, pick an image and a buildertaggedImage from hashes if they exists.
// otherways fallback to the pushed repo // otherways fallback to the pushed repo
// Resolve images from the hashtree // Resolve images from the hashtree
sourceImage = cs.resolveExistingImageHash(assertion.Hash.BuildHash, compileSpec) sourceImage = cs.resolveExistingImageHash(assertion.Hash.BuildHash, compileSpec)
Debug(pkgTag, " :wrench: Compiling "+compileSpec.GetPackage().HumanReadableString()+" from tree") cs.Options.Context.Debug(pkgTag, " :wrench: Compiling "+compileSpec.GetPackage().HumanReadableString()+" from tree")
} }
a, err := cs.compileWithImage( a, err := cs.compileWithImage(
@ -1128,7 +1128,7 @@ func (cs *LuetCompiler) compile(concurrency int, keepPermissions bool, generateF
a.PackageCacheImage = assertion.Hash.PackageHash a.PackageCacheImage = assertion.Hash.PackageHash
Info(pkgTag, ":white_check_mark: Done") cs.Options.Context.Info(pkgTag, ":white_check_mark: Done")
bus.Manager.Publish(bus.EventPackagePostBuild, struct { bus.Manager.Publish(bus.EventPackagePostBuild, struct {
CompileSpec *compilerspec.LuetCompilationSpec CompileSpec *compilerspec.LuetCompilationSpec
@ -1148,8 +1148,8 @@ func (cs *LuetCompiler) compile(concurrency int, keepPermissions bool, generateF
localGenerateArtifact = *generateFinalArtifact localGenerateArtifact = *generateFinalArtifact
} }
resolvedSourceImage := cs.resolveExistingImageHash(packageHashTree.SourceHash, p) resolvedSourceImage := cs.resolveExistingImageHash(packageHashTree.SourceHash, p)
Info(":rocket: All dependencies are satisfied, building package requested by the user", p.GetPackage().HumanReadableString()) cs.Options.Context.Info(":rocket: All dependencies are satisfied, building package requested by the user", p.GetPackage().HumanReadableString())
Info(":package:", p.GetPackage().HumanReadableString(), " Using image: ", resolvedSourceImage) cs.Options.Context.Info(":package:", p.GetPackage().HumanReadableString(), " Using image: ", resolvedSourceImage)
a, err := cs.compileWithImage(resolvedSourceImage, packageHashTree.BuilderImageHash, targetAssertion.Hash.PackageHash, concurrency, keepPermissions, cs.Options.KeepImg, p, localGenerateArtifact) a, err := cs.compileWithImage(resolvedSourceImage, packageHashTree.BuilderImageHash, targetAssertion.Hash.PackageHash, concurrency, keepPermissions, cs.Options.KeepImg, p, localGenerateArtifact)
if err != nil { if err != nil {
return a, err return a, err
@ -1271,7 +1271,7 @@ func (cs *LuetCompiler) FromPackage(p pkg.Package) (*compilerspec.LuetCompilatio
opts := options.Compiler{} opts := options.Compiler{}
artifactMetadataFile := filepath.Join(pack.GetTreeDir(), "..", pack.GetMetadataFilePath()) artifactMetadataFile := filepath.Join(pack.GetTreeDir(), "..", pack.GetMetadataFilePath())
Debug("Checking if metadata file is present", artifactMetadataFile) cs.Options.Context.Debug("Checking if metadata file is present", artifactMetadataFile)
if _, err := os.Stat(artifactMetadataFile); err == nil { if _, err := os.Stat(artifactMetadataFile); err == nil {
f, err := os.Open(artifactMetadataFile) f, err := os.Open(artifactMetadataFile)
if err != nil { if err != nil {
@ -1286,14 +1286,14 @@ func (cs *LuetCompiler) FromPackage(p pkg.Package) (*compilerspec.LuetCompilatio
return nil, errors.Wrap(err, "could not decode package from yaml") return nil, errors.Wrap(err, "could not decode package from yaml")
} }
Debug("Read build options:", art.CompileSpec.BuildOptions, "from", artifactMetadataFile) cs.Options.Context.Debug("Read build options:", art.CompileSpec.BuildOptions, "from", artifactMetadataFile)
if art.CompileSpec.BuildOptions != nil { if art.CompileSpec.BuildOptions != nil {
opts = *art.CompileSpec.BuildOptions opts = *art.CompileSpec.BuildOptions
} }
} else if !os.IsNotExist(err) { } else if !os.IsNotExist(err) {
Debug("error reading artifact metadata file: ", err.Error()) cs.Options.Context.Debug("error reading artifact metadata file: ", err.Error())
} else if os.IsNotExist(err) { } else if os.IsNotExist(err) {
Debug("metadata file not present, skipping", artifactMetadataFile) cs.Options.Context.Debug("metadata file not present, skipping", artifactMetadataFile)
} }
// Update processed build values // Update processed build values

View File

@ -18,14 +18,11 @@ package compiler_test
import ( import (
"testing" "testing"
. "github.com/mudler/luet/cmd/util"
. "github.com/onsi/ginkgo" . "github.com/onsi/ginkgo"
. "github.com/onsi/gomega" . "github.com/onsi/gomega"
) )
func TestSolver(t *testing.T) { func TestSolver(t *testing.T) {
RegisterFailHandler(Fail) RegisterFailHandler(Fail)
LoadConfig()
RunSpecs(t, "Compiler Suite") RunSpecs(t, "Compiler Suite")
} }

View File

@ -19,6 +19,7 @@ import (
"io/ioutil" "io/ioutil"
"os" "os"
"github.com/mudler/luet/pkg/api/core/types"
. "github.com/mudler/luet/pkg/compiler" . "github.com/mudler/luet/pkg/compiler"
sd "github.com/mudler/luet/pkg/compiler/backend" sd "github.com/mudler/luet/pkg/compiler/backend"
"github.com/mudler/luet/pkg/compiler/types/compression" "github.com/mudler/luet/pkg/compiler/types/compression"
@ -33,6 +34,8 @@ import (
) )
var _ = Describe("Compiler", func() { var _ = Describe("Compiler", func() {
ctx := types.NewContext()
Context("Simple package build definition", func() { Context("Simple package build definition", func() {
It("Compiles it correctly", func() { It("Compiles it correctly", func() {
generalRecipe := tree.NewCompilerRecipe(pkg.NewInMemoryDatabase(false)) generalRecipe := tree.NewCompilerRecipe(pkg.NewInMemoryDatabase(false))
@ -42,7 +45,7 @@ var _ = Describe("Compiler", func() {
Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(3)) Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(3))
compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(), generalRecipe.GetDatabase(), options.Concurrency(2)) compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase(), options.Concurrency(2), options.WithContext(types.NewContext()))
spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}) spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"})
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
@ -85,7 +88,7 @@ var _ = Describe("Compiler", func() {
Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(3)) Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(3))
compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(), generalRecipe.GetDatabase(), options.Concurrency(2)) compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase(), options.Concurrency(2), options.WithContext(types.NewContext()))
spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "c", Category: "test", Version: "1.2"}) spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "c", Category: "test", Version: "1.2"})
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
@ -115,7 +118,7 @@ var _ = Describe("Compiler", func() {
Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(3)) Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(3))
compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(), generalRecipe.GetDatabase(), options.Concurrency(2)) compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase(), options.Concurrency(2), options.WithContext(types.NewContext()))
spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "c", Category: "test", Version: "1.2"}) spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "c", Category: "test", Version: "1.2"})
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
@ -147,7 +150,7 @@ var _ = Describe("Compiler", func() {
Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(3)) Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(3))
compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(), generalRecipe.GetDatabase(), options.Concurrency(1)) compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase(), options.Concurrency(1), options.WithContext(types.NewContext()))
spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}) spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"})
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
@ -181,7 +184,7 @@ var _ = Describe("Compiler", func() {
err = generalRecipe.Load("../../tests/fixtures/templates") err = generalRecipe.Load("../../tests/fixtures/templates")
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(), generalRecipe.GetDatabase()) compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase(), options.WithContext(types.NewContext()))
Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(1)) Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(1))
pkg, err := generalRecipe.GetDatabase().FindPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}) pkg, err := generalRecipe.GetDatabase().FindPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"})
@ -205,7 +208,7 @@ var _ = Describe("Compiler", func() {
Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(4)) Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(4))
compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(), generalRecipe.GetDatabase(), options.Concurrency(2)) compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase(), options.Concurrency(2), options.WithContext(types.NewContext()))
spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "c", Category: "test", Version: "1.0"}) spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "c", Category: "test", Version: "1.0"})
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
@ -261,7 +264,7 @@ var _ = Describe("Compiler", func() {
Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(2)) Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(2))
compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(), generalRecipe.GetDatabase(), options.Concurrency(1)) compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase(), options.Concurrency(1), options.WithContext(types.NewContext()))
spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "extra", Category: "layer", Version: "1.0"}) spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "extra", Category: "layer", Version: "1.0"})
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
@ -302,7 +305,7 @@ var _ = Describe("Compiler", func() {
Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(1)) Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(1))
compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(), generalRecipe.GetDatabase()) compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase())
spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}) spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"})
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
@ -336,7 +339,7 @@ var _ = Describe("Compiler", func() {
Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(1)) Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(1))
compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(), generalRecipe.GetDatabase()) compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase())
spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}) spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"})
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
@ -371,7 +374,7 @@ var _ = Describe("Compiler", func() {
Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(1)) Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(1))
compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(), generalRecipe.GetDatabase()) compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase())
spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}) spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"})
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
@ -406,7 +409,7 @@ var _ = Describe("Compiler", func() {
Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(2)) Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(2))
compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(), generalRecipe.GetDatabase()) compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase())
spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}) spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"})
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
@ -439,7 +442,7 @@ var _ = Describe("Compiler", func() {
Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(2)) Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(2))
compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(), generalRecipe.GetDatabase()) compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase())
spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}) spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"})
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
@ -472,7 +475,7 @@ var _ = Describe("Compiler", func() {
Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(2)) Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(2))
compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(), generalRecipe.GetDatabase()) compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase())
spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}) spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"})
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
@ -509,7 +512,7 @@ var _ = Describe("Compiler", func() {
Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(3)) Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(3))
compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(), generalRecipe.GetDatabase()) compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase())
spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "pkgs-checker", Category: "package", Version: "9999"}) spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "pkgs-checker", Category: "package", Version: "9999"})
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
@ -549,7 +552,7 @@ var _ = Describe("Compiler", func() {
Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(3)) Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(3))
compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(), generalRecipe.GetDatabase()) compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase())
spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "d", Category: "test", Version: "1.0"}) spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "d", Category: "test", Version: "1.0"})
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
@ -592,7 +595,7 @@ var _ = Describe("Compiler", func() {
Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(3)) Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(3))
compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(), generalRecipe.GetDatabase()) compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase())
spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "d", Category: "test", Version: "1.0"}) spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "d", Category: "test", Version: "1.0"})
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
@ -633,7 +636,7 @@ var _ = Describe("Compiler", func() {
Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(3)) Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(3))
compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(), generalRecipe.GetDatabase()) compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase())
spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "extra", Category: "layer", Version: "0.1"}) spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "extra", Category: "layer", Version: "0.1"})
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
@ -667,7 +670,7 @@ var _ = Describe("Compiler", func() {
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(10)) Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(10))
compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(), generalRecipe.GetDatabase()) compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase())
spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "vhba", Category: "sys-fs-5.4.2", Version: "20190410"}) spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "vhba", Category: "sys-fs-5.4.2", Version: "20190410"})
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
@ -695,7 +698,7 @@ var _ = Describe("Compiler", func() {
Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(10)) Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(10))
compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(), generalRecipe.GetDatabase()) compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase())
spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "vhba", Category: "sys-fs-5.4.2", Version: "20190410"}) spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "vhba", Category: "sys-fs-5.4.2", Version: "20190410"})
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
@ -734,7 +737,7 @@ var _ = Describe("Compiler", func() {
Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(4)) Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(4))
compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(), generalRecipe.GetDatabase()) compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase())
spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}) spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"})
@ -786,7 +789,7 @@ var _ = Describe("Compiler", func() {
Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(3)) Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(3))
compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(), generalRecipe.GetDatabase(), options.Concurrency(2)) compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase(), options.Concurrency(2), options.WithContext(types.NewContext()))
spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "c", Category: "test", Version: "1.0"}) spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "c", Category: "test", Version: "1.0"})
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
@ -828,7 +831,7 @@ var _ = Describe("Compiler", func() {
Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(2)) Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(2))
compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(), generalRecipe.GetDatabase()) compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase())
spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "runtime", Category: "layer", Version: "0.1"}) spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "runtime", Category: "layer", Version: "0.1"})
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
@ -860,7 +863,7 @@ var _ = Describe("Compiler", func() {
Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(2)) Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(2))
compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(), generalRecipe.GetDatabase()) compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase())
spec, err := compiler.FromPackage(&pkg.DefaultPackage{ spec, err := compiler.FromPackage(&pkg.DefaultPackage{
Name: "dironly", Name: "dironly",
@ -913,7 +916,7 @@ var _ = Describe("Compiler", func() {
Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(2)) Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(2))
compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(), generalRecipe.GetDatabase()) compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase(), options.WithContext(types.NewContext()))
spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "runtime", Category: "layer", Version: "0.1"}) spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "runtime", Category: "layer", Version: "0.1"})
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
@ -932,7 +935,7 @@ var _ = Describe("Compiler", func() {
Expect(len(artifacts[0].Dependencies)).To(Equal(1)) Expect(len(artifacts[0].Dependencies)).To(Equal(1))
Expect(fileHelper.Exists(spec.Rel("runtime-layer-0.1.package.tar.gz"))).To(BeTrue()) Expect(fileHelper.Exists(spec.Rel("runtime-layer-0.1.package.tar.gz"))).To(BeTrue())
Expect(fileHelper.Exists(spec.Rel("runtime-layer-0.1.package.tar"))).To(BeFalse()) Expect(fileHelper.Exists(spec.Rel("runtime-layer-0.1.package.tar"))).To(BeFalse())
Expect(artifacts[0].Unpack(tmpdir, false)).ToNot(HaveOccurred()) Expect(artifacts[0].Unpack(ctx, tmpdir, false)).ToNot(HaveOccurred())
// Expect(helpers.Untar(spec.Rel("runtime-layer-0.1.package.tar"), tmpdir, false)).ToNot(HaveOccurred()) // Expect(helpers.Untar(spec.Rel("runtime-layer-0.1.package.tar"), tmpdir, false)).ToNot(HaveOccurred())
Expect(fileHelper.Exists(spec.Rel("bin/busybox"))).To(BeTrue()) Expect(fileHelper.Exists(spec.Rel("bin/busybox"))).To(BeTrue())
Expect(fileHelper.Exists(spec.Rel("var"))).ToNot(BeTrue()) Expect(fileHelper.Exists(spec.Rel("var"))).ToNot(BeTrue())
@ -948,7 +951,7 @@ var _ = Describe("Compiler", func() {
err := generalRecipe.Load("../../tests/fixtures/includeimage") err := generalRecipe.Load("../../tests/fixtures/includeimage")
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(2)) Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(2))
compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(), generalRecipe.GetDatabase()) compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase(), options.WithContext(types.NewContext()))
specs, err := compiler.FromDatabase(generalRecipe.GetDatabase(), true, "") specs, err := compiler.FromDatabase(generalRecipe.GetDatabase(), true, "")
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
@ -967,7 +970,7 @@ var _ = Describe("Compiler", func() {
Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(2)) Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(2))
compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(), generalRecipe.GetDatabase()) compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase(), options.WithContext(types.NewContext()))
spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "runtime", Category: "layer", Version: "0.1"}) spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "runtime", Category: "layer", Version: "0.1"})
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())

View File

@ -18,8 +18,8 @@ package compiler
import ( import (
"fmt" "fmt"
"github.com/mudler/luet/pkg/api/core/types"
compilerspec "github.com/mudler/luet/pkg/compiler/types/spec" compilerspec "github.com/mudler/luet/pkg/compiler/types/spec"
"github.com/mudler/luet/pkg/config"
pkg "github.com/mudler/luet/pkg/package" pkg "github.com/mudler/luet/pkg/package"
"github.com/mudler/luet/pkg/solver" "github.com/mudler/luet/pkg/solver"
"github.com/pkg/errors" "github.com/pkg/errors"
@ -32,7 +32,7 @@ import (
// which identifies a Package in a HashTree // which identifies a Package in a HashTree
type ImageHashTree struct { type ImageHashTree struct {
Database pkg.PackageDatabase Database pkg.PackageDatabase
SolverOptions config.LuetSolverOptions SolverOptions types.LuetSolverOptions
} }
// PackageImageHashTree represent the Package into a given image hash tree // PackageImageHashTree represent the Package into a given image hash tree

View File

@ -16,6 +16,7 @@
package compiler_test package compiler_test
import ( import (
"github.com/mudler/luet/pkg/api/core/types"
. "github.com/mudler/luet/pkg/compiler" . "github.com/mudler/luet/pkg/compiler"
sd "github.com/mudler/luet/pkg/compiler/backend" sd "github.com/mudler/luet/pkg/compiler/backend"
"github.com/mudler/luet/pkg/compiler/types/options" "github.com/mudler/luet/pkg/compiler/types/options"
@ -26,15 +27,16 @@ import (
) )
var _ = Describe("ImageHashTree", func() { var _ = Describe("ImageHashTree", func() {
ctx := types.NewContext()
generalRecipe := tree.NewCompilerRecipe(pkg.NewInMemoryDatabase(false)) generalRecipe := tree.NewCompilerRecipe(pkg.NewInMemoryDatabase(false))
compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(), generalRecipe.GetDatabase(), options.Concurrency(2)) compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase(), options.Concurrency(2))
hashtree := NewHashTree(generalRecipe.GetDatabase()) hashtree := NewHashTree(generalRecipe.GetDatabase())
Context("Simple package definition", func() { Context("Simple package definition", func() {
BeforeEach(func() { BeforeEach(func() {
generalRecipe = tree.NewCompilerRecipe(pkg.NewInMemoryDatabase(false)) generalRecipe = tree.NewCompilerRecipe(pkg.NewInMemoryDatabase(false))
err := generalRecipe.Load("../../tests/fixtures/buildable") err := generalRecipe.Load("../../tests/fixtures/buildable")
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
compiler = NewLuetCompiler(sd.NewSimpleDockerBackend(), generalRecipe.GetDatabase(), options.Concurrency(2)) compiler = NewLuetCompiler(sd.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase(), options.Concurrency(2))
hashtree = NewHashTree(generalRecipe.GetDatabase()) hashtree = NewHashTree(generalRecipe.GetDatabase())
}) })
@ -60,7 +62,7 @@ var _ = Describe("ImageHashTree", func() {
err := generalRecipe.Load("../../tests/fixtures/upgrade_old_repo_revision") err := generalRecipe.Load("../../tests/fixtures/upgrade_old_repo_revision")
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
compiler = NewLuetCompiler(sd.NewSimpleDockerBackend(), generalRecipe.GetDatabase(), options.Concurrency(2)) compiler = NewLuetCompiler(sd.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase(), options.Concurrency(2))
hashtree = NewHashTree(generalRecipe.GetDatabase()) hashtree = NewHashTree(generalRecipe.GetDatabase())
}) })
@ -103,7 +105,7 @@ var _ = Describe("ImageHashTree", func() {
//Definition of A here is slightly changed in the steps build.yaml file (1 character only) //Definition of A here is slightly changed in the steps build.yaml file (1 character only)
err := generalRecipe.Load("../../tests/fixtures/upgrade_old_repo_revision_content_changed") err := generalRecipe.Load("../../tests/fixtures/upgrade_old_repo_revision_content_changed")
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
compiler = NewLuetCompiler(sd.NewSimpleDockerBackend(), generalRecipe.GetDatabase(), options.Concurrency(2)) compiler = NewLuetCompiler(sd.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase(), options.Concurrency(2))
hashtree = NewHashTree(generalRecipe.GetDatabase()) hashtree = NewHashTree(generalRecipe.GetDatabase())
}) })

View File

@ -18,8 +18,8 @@ package options
import ( import (
"runtime" "runtime"
"github.com/mudler/luet/pkg/api/core/types"
"github.com/mudler/luet/pkg/compiler/types/compression" "github.com/mudler/luet/pkg/compiler/types/compression"
"github.com/mudler/luet/pkg/config"
"github.com/mudler/luet/pkg/solver" "github.com/mudler/luet/pkg/solver"
) )
@ -33,7 +33,7 @@ type Compiler struct {
Wait bool Wait bool
OnlyDeps bool OnlyDeps bool
NoDeps bool NoDeps bool
SolverOptions config.LuetSolverOptions SolverOptions types.LuetSolverOptions
BuildValuesFile []string BuildValuesFile []string
BuildValues []map[string]interface{} BuildValues []map[string]interface{}
@ -46,6 +46,8 @@ type Compiler struct {
// TemplatesFolder. should default to tree/templates // TemplatesFolder. should default to tree/templates
TemplatesFolder []string TemplatesFolder []string
Context *types.Context
} }
func NewDefaultCompiler() *Compiler { func NewDefaultCompiler() *Compiler {
@ -58,7 +60,7 @@ func NewDefaultCompiler() *Compiler {
Concurrency: runtime.NumCPU(), Concurrency: runtime.NumCPU(),
OnlyDeps: false, OnlyDeps: false,
NoDeps: false, NoDeps: false,
SolverOptions: config.LuetSolverOptions{Options: solver.Options{Concurrency: 1, Type: solver.SingleCoreSimple}}, SolverOptions: types.LuetSolverOptions{Options: solver.Options{Concurrency: 1, Type: solver.SingleCoreSimple}},
} }
} }
@ -201,9 +203,16 @@ func WithCompressionType(t compression.Implementation) func(cfg *Compiler) error
} }
} }
func WithSolverOptions(c config.LuetSolverOptions) func(cfg *Compiler) error { func WithSolverOptions(c types.LuetSolverOptions) func(cfg *Compiler) error {
return func(cfg *Compiler) error { return func(cfg *Compiler) error {
cfg.SolverOptions = c cfg.SolverOptions = c
return nil return nil
} }
} }
func WithContext(c *types.Context) func(cfg *Compiler) error {
return func(cfg *Compiler) error {
cfg.Context = c
return nil
}
}

View File

@ -18,14 +18,11 @@ package compilerspec_test
import ( import (
"testing" "testing"
. "github.com/mudler/luet/cmd/util"
. "github.com/onsi/ginkgo" . "github.com/onsi/ginkgo"
. "github.com/onsi/gomega" . "github.com/onsi/gomega"
) )
func TestSpec(t *testing.T) { func TestSpec(t *testing.T) {
RegisterFailHandler(Fail) RegisterFailHandler(Fail)
LoadConfig()
RunSpecs(t, "Spec Suite") RunSpecs(t, "Spec Suite")
} }

View File

@ -1,66 +0,0 @@
// Copyright © 2019-2020 Ettore Di Giacinto <mudler@gentoo.org>
// Daniele Rondina <geaaru@sabayonlinux.org>
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, see <http://www.gnu.org/licenses/>.
package config_test
import (
"os"
"path/filepath"
"strings"
config "github.com/mudler/luet/pkg/config"
fileHelper "github.com/mudler/luet/pkg/helpers/file"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
var _ = Describe("Config", func() {
Context("Simple temporary directory creation", func() {
It("Create Temporary directory", func() {
// PRE: tmpdir_base contains default value.
tmpDir, err := config.LuetCfg.GetSystem().TempDir("test1")
Expect(err).ToNot(HaveOccurred())
Expect(strings.HasPrefix(tmpDir, filepath.Join(os.TempDir(), "tmpluet"))).To(BeTrue())
Expect(fileHelper.Exists(tmpDir)).To(BeTrue())
defer os.RemoveAll(tmpDir)
})
It("Create Temporary file", func() {
// PRE: tmpdir_base contains default value.
tmpFile, err := config.LuetCfg.GetSystem().TempFile("testfile1")
Expect(err).ToNot(HaveOccurred())
Expect(strings.HasPrefix(tmpFile.Name(), filepath.Join(os.TempDir(), "tmpluet"))).To(BeTrue())
Expect(fileHelper.Exists(tmpFile.Name())).To(BeTrue())
defer os.Remove(tmpFile.Name())
})
It("Config1", func() {
cfg := config.LuetCfg
cfg.GetLogging().Color = false
Expect(cfg.GetLogging().Color).To(BeFalse())
})
})
})

View File

@ -18,14 +18,11 @@ package helpers_test
import ( import (
"testing" "testing"
. "github.com/mudler/luet/cmd/util"
. "github.com/onsi/ginkgo" . "github.com/onsi/ginkgo"
. "github.com/onsi/gomega" . "github.com/onsi/gomega"
) )
func TestSolver(t *testing.T) { func TestSolver(t *testing.T) {
RegisterFailHandler(Fail) RegisterFailHandler(Fail)
LoadConfig()
RunSpecs(t, "Helpers Suite") RunSpecs(t, "Helpers Suite")
} }

View File

@ -36,6 +36,7 @@ func packsToList(p pkg.Packages) string {
} }
func printList(p pkg.Packages) { func printList(p pkg.Packages) {
fmt.Println()
d := pterm.TableData{{"Program Name", "Version", "License"}} d := pterm.TableData{{"Program Name", "Version", "License"}}
for _, m := range p { for _, m := range p {
d = append(d, []string{ d = append(d, []string{
@ -43,9 +44,12 @@ func printList(p pkg.Packages) {
pterm.LightGreen(m.GetVersion()), m.GetLicense()}) pterm.LightGreen(m.GetVersion()), m.GetLicense()})
} }
pterm.DefaultTable.WithHasHeader().WithData(d).Render() pterm.DefaultTable.WithHasHeader().WithData(d).Render()
fmt.Println()
} }
func printUpgradeList(install, uninstall pkg.Packages) { func printUpgradeList(install, uninstall pkg.Packages) {
fmt.Println()
d := pterm.TableData{{"Old version", "New version", "License"}} d := pterm.TableData{{"Old version", "New version", "License"}}
for _, m := range uninstall { for _, m := range uninstall {
if p, err := install.Find(m.GetPackageName()); err == nil { if p, err := install.Find(m.GetPackageName()); err == nil {
@ -64,6 +68,8 @@ func printUpgradeList(install, uninstall pkg.Packages) {
} }
} }
pterm.DefaultTable.WithHasHeader().WithData(d).Render() pterm.DefaultTable.WithHasHeader().WithData(d).Render()
fmt.Println()
} }
func printMatchUpgrade(artefacts map[string]ArtifactMatch, uninstall pkg.Packages) { func printMatchUpgrade(artefacts map[string]ArtifactMatch, uninstall pkg.Packages) {
@ -77,6 +83,7 @@ func printMatchUpgrade(artefacts map[string]ArtifactMatch, uninstall pkg.Package
} }
func printMatches(artefacts map[string]ArtifactMatch) { func printMatches(artefacts map[string]ArtifactMatch) {
fmt.Println()
d := pterm.TableData{{"Program Name", "Version", "License", "Repository"}} d := pterm.TableData{{"Program Name", "Version", "License", "Repository"}}
for _, m := range artefacts { for _, m := range artefacts {
d = append(d, []string{ d = append(d, []string{
@ -84,14 +91,5 @@ func printMatches(artefacts map[string]ArtifactMatch) {
pterm.LightGreen(m.Package.GetVersion()), m.Package.GetLicense(), m.Repository.Name}) pterm.LightGreen(m.Package.GetVersion()), m.Package.GetLicense(), m.Repository.Name})
} }
pterm.DefaultTable.WithHasHeader().WithData(d).Render() pterm.DefaultTable.WithHasHeader().WithData(d).Render()
} fmt.Println()
func matchesToList(artefacts map[string]ArtifactMatch) string {
var packs []string
for fingerprint, match := range artefacts {
packs = append(packs, fmt.Sprintf("%s (%s)", fingerprint, match.Repository.GetName()))
}
sort.Strings(packs)
return strings.Join(packs, " ")
} }

View File

@ -18,19 +18,11 @@ package client_test
import ( import (
"testing" "testing"
. "github.com/mudler/luet/cmd/util"
config "github.com/mudler/luet/pkg/config"
. "github.com/onsi/ginkgo" . "github.com/onsi/ginkgo"
. "github.com/onsi/gomega" . "github.com/onsi/gomega"
) )
func TestClient(t *testing.T) { func TestClient(t *testing.T) {
RegisterFailHandler(Fail) RegisterFailHandler(Fail)
LoadConfig()
// Set temporary directory for rootfs
config.LuetCfg.GetSystem().Rootfs = "/tmp/luet-root"
// Force dynamic path for packages cache
config.LuetCfg.GetSystem().PkgsCachePath = ""
RunSpecs(t, "Client Suite") RunSpecs(t, "Client Suite")
} }

View File

@ -26,11 +26,11 @@ import (
"github.com/docker/go-units" "github.com/docker/go-units"
"github.com/pkg/errors" "github.com/pkg/errors"
luetTypes "github.com/mudler/luet/pkg/api/core/types"
"github.com/mudler/luet/pkg/api/core/types/artifact" "github.com/mudler/luet/pkg/api/core/types/artifact"
"github.com/mudler/luet/pkg/config"
"github.com/mudler/luet/pkg/helpers/docker" "github.com/mudler/luet/pkg/helpers/docker"
fileHelper "github.com/mudler/luet/pkg/helpers/file" fileHelper "github.com/mudler/luet/pkg/helpers/file"
. "github.com/mudler/luet/pkg/logger"
) )
const ( const (
@ -40,18 +40,19 @@ const (
type DockerClient struct { type DockerClient struct {
RepoData RepoData RepoData RepoData
auth *types.AuthConfig auth *types.AuthConfig
verify bool
Cache *artifact.ArtifactCache Cache *artifact.ArtifactCache
context *luetTypes.Context
} }
func NewDockerClient(r RepoData) *DockerClient { func NewDockerClient(r RepoData, ctx *luetTypes.Context) *DockerClient {
auth := &types.AuthConfig{} auth := &types.AuthConfig{}
dat, _ := json.Marshal(r.Authentication) dat, _ := json.Marshal(r.Authentication)
json.Unmarshal(dat, auth) json.Unmarshal(dat, auth)
return &DockerClient{RepoData: r, auth: auth, return &DockerClient{RepoData: r, auth: auth,
Cache: artifact.NewCache(config.LuetCfg.GetSystem().GetSystemPkgsCacheDirPath()), Cache: artifact.NewCache(ctx.Config.GetSystem().GetSystemPkgsCacheDirPath()),
context: ctx,
} }
} }
@ -59,8 +60,8 @@ func (c *DockerClient) DownloadArtifact(a *artifact.PackageArtifact) (*artifact.
//var u *url.URL = nil //var u *url.URL = nil
var err error var err error
Spinner(22) c.context.Spinner()
defer SpinnerStop() defer c.context.SpinnerStop()
resultingArtifact := a.ShallowCopy() resultingArtifact := a.ShallowCopy()
artifactName := path.Base(a.Path) artifactName := path.Base(a.Path)
@ -81,16 +82,16 @@ func (c *DockerClient) DownloadArtifact(a *artifact.PackageArtifact) (*artifact.
resultingArtifact = a resultingArtifact = a
resultingArtifact.Path = fileName resultingArtifact.Path = fileName
resultingArtifact.Checksums = artifact.Checksums{} resultingArtifact.Checksums = artifact.Checksums{}
Debug("Use artifact", artifactName, "from cache.") c.context.Debug("Use artifact", artifactName, "from cache.")
} else { } else {
temp, err := config.LuetCfg.GetSystem().TempDir("image") temp, err := c.context.Config.GetSystem().TempDir("image")
if err != nil { if err != nil {
return nil, err return nil, err
} }
defer os.RemoveAll(temp) defer os.RemoveAll(temp)
tempArtifact, err := config.LuetCfg.GetSystem().TempFile("artifact") tempArtifact, err := c.context.Config.GetSystem().TempFile("artifact")
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -98,43 +99,43 @@ func (c *DockerClient) DownloadArtifact(a *artifact.PackageArtifact) (*artifact.
for _, uri := range c.RepoData.Urls { for _, uri := range c.RepoData.Urls {
imageName := fmt.Sprintf("%s:%s", uri, a.CompileSpec.GetPackage().ImageID()) imageName := fmt.Sprintf("%s:%s", uri, a.CompileSpec.GetPackage().ImageID())
Info("Downloading image", imageName) c.context.Info("Downloading image", imageName)
contentstore, err := config.LuetCfg.GetSystem().TempDir("contentstore") contentstore, err := c.context.Config.GetSystem().TempDir("contentstore")
if err != nil { if err != nil {
Warning("Cannot create contentstore", err.Error()) c.context.Warning("Cannot create contentstore", err.Error())
continue continue
} }
// imageName := fmt.Sprintf("%s/%s", uri, artifact.GetCompileSpec().GetPackage().GetPackageImageName()) // imageName := fmt.Sprintf("%s/%s", uri, artifact.GetCompileSpec().GetPackage().GetPackageImageName())
info, err := docker.DownloadAndExtractDockerImage(contentstore, imageName, temp, c.auth, c.RepoData.Verify) info, err := docker.DownloadAndExtractDockerImage(contentstore, imageName, temp, c.auth, c.RepoData.Verify)
if err != nil { if err != nil {
Warning(fmt.Sprintf(errImageDownloadMsg, imageName, err.Error())) c.context.Warning(fmt.Sprintf(errImageDownloadMsg, imageName, err.Error()))
continue continue
} }
Info(fmt.Sprintf("Pulled: %s", info.Target.Digest)) c.context.Info(fmt.Sprintf("Pulled: %s", info.Target.Digest))
Info(fmt.Sprintf("Size: %s", units.BytesSize(float64(info.Target.Size)))) c.context.Info(fmt.Sprintf("Size: %s", units.BytesSize(float64(info.Target.Size))))
Debug("\nCompressing result ", filepath.Join(temp), "to", tempArtifact.Name()) c.context.Debug("\nCompressing result ", filepath.Join(temp), "to", tempArtifact.Name())
// We discard checksum, that are checked while during pull and unpack // We discard checksum, that are checked while during pull and unpack
resultingArtifact.Checksums = artifact.Checksums{} resultingArtifact.Checksums = artifact.Checksums{}
resultingArtifact.Path = tempArtifact.Name() // First set to cache file resultingArtifact.Path = tempArtifact.Name() // First set to cache file
err = resultingArtifact.Compress(temp, 1) err = resultingArtifact.Compress(temp, 1)
if err != nil { if err != nil {
Error(fmt.Sprintf("Failed compressing package %s: %s", imageName, err.Error())) c.context.Error(fmt.Sprintf("Failed compressing package %s: %s", imageName, err.Error()))
continue continue
} }
_, _, err = c.Cache.Put(resultingArtifact) _, _, err = c.Cache.Put(resultingArtifact)
if err != nil { if err != nil {
Error(fmt.Sprintf("Failed storing package %s from cache: %s", imageName, err.Error())) c.context.Error(fmt.Sprintf("Failed storing package %s from cache: %s", imageName, err.Error()))
continue continue
} }
fileName, err := c.Cache.Get(resultingArtifact) fileName, err := c.Cache.Get(resultingArtifact)
if err != nil { if err != nil {
Error(fmt.Sprintf("Failed getting package %s from cache: %s", imageName, err.Error())) c.context.Error(fmt.Sprintf("Failed getting package %s from cache: %s", imageName, err.Error()))
continue continue
} }
@ -159,36 +160,36 @@ func (c *DockerClient) DownloadFile(name string) (string, error) {
// Files should be in URI/repository:<file> // Files should be in URI/repository:<file>
ok := false ok := false
temp, err = config.LuetCfg.GetSystem().TempDir("tree") temp, err = c.context.Config.GetSystem().TempDir("tree")
if err != nil { if err != nil {
return "", err return "", err
} }
for _, uri := range c.RepoData.Urls { for _, uri := range c.RepoData.Urls {
file, err = config.LuetCfg.GetSystem().TempFile("DockerClient") file, err = c.context.Config.GetSystem().TempFile("DockerClient")
if err != nil { if err != nil {
continue continue
} }
contentstore, err = config.LuetCfg.GetSystem().TempDir("contentstore") contentstore, err = c.context.Config.GetSystem().TempDir("contentstore")
if err != nil { if err != nil {
Warning("Cannot create contentstore", err.Error()) c.context.Warning("Cannot create contentstore", err.Error())
continue continue
} }
imageName := fmt.Sprintf("%s:%s", uri, docker.StripInvalidStringsFromImage(name)) imageName := fmt.Sprintf("%s:%s", uri, docker.StripInvalidStringsFromImage(name))
Info("Downloading", imageName) c.context.Info("Downloading", imageName)
info, err := docker.DownloadAndExtractDockerImage(contentstore, imageName, temp, c.auth, c.RepoData.Verify) info, err := docker.DownloadAndExtractDockerImage(contentstore, imageName, temp, c.auth, c.RepoData.Verify)
if err != nil { if err != nil {
Warning(fmt.Sprintf(errImageDownloadMsg, imageName, err.Error())) c.context.Warning(fmt.Sprintf(errImageDownloadMsg, imageName, err.Error()))
continue continue
} }
Info(fmt.Sprintf("Pulled: %s", info.Target.Digest)) c.context.Info(fmt.Sprintf("Pulled: %s", info.Target.Digest))
Info(fmt.Sprintf("Size: %s", units.BytesSize(float64(info.Target.Size)))) c.context.Info(fmt.Sprintf("Size: %s", units.BytesSize(float64(info.Target.Size))))
Debug("\nCopying file ", filepath.Join(temp, name), "to", file.Name()) c.context.Debug("\nCopying file ", filepath.Join(temp, name), "to", file.Name())
err = fileHelper.CopyFile(filepath.Join(temp, name), file.Name()) err = fileHelper.CopyFile(filepath.Join(temp, name), file.Name())
if err != nil { if err != nil {
continue continue

View File

@ -1,4 +1,4 @@
// Copyright © 2019 Ettore Di Giacinto <mudler@gentoo.org> // Copyright © 2019-2021 Ettore Di Giacinto <mudler@gentoo.org>
// //
// This program is free software; you can redistribute it and/or modify // This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
@ -20,6 +20,7 @@ import (
"os" "os"
"path/filepath" "path/filepath"
"github.com/mudler/luet/pkg/api/core/types"
"github.com/mudler/luet/pkg/api/core/types/artifact" "github.com/mudler/luet/pkg/api/core/types/artifact"
compilerspec "github.com/mudler/luet/pkg/compiler/types/spec" compilerspec "github.com/mudler/luet/pkg/compiler/types/spec"
fileHelper "github.com/mudler/luet/pkg/helpers/file" fileHelper "github.com/mudler/luet/pkg/helpers/file"
@ -37,6 +38,8 @@ import (
// mount/unmount layers. // mount/unmount layers.
var _ = Describe("Docker client", func() { var _ = Describe("Docker client", func() {
Context("With repository", func() { Context("With repository", func() {
ctx := types.NewContext()
repoImage := os.Getenv("UNIT_TEST_DOCKER_IMAGE") repoImage := os.Getenv("UNIT_TEST_DOCKER_IMAGE")
var repoURL []string var repoURL []string
var c *DockerClient var c *DockerClient
@ -45,7 +48,7 @@ var _ = Describe("Docker client", func() {
Skip("UNIT_TEST_DOCKER_IMAGE not specified") Skip("UNIT_TEST_DOCKER_IMAGE not specified")
} }
repoURL = []string{repoImage} repoURL = []string{repoImage}
c = NewDockerClient(RepoData{Urls: repoURL}) c = NewDockerClient(RepoData{Urls: repoURL}, ctx)
}) })
It("Downloads single files", func() { It("Downloads single files", func() {
@ -70,7 +73,8 @@ var _ = Describe("Docker client", func() {
tmpdir, err := ioutil.TempDir("", "test") tmpdir, err := ioutil.TempDir("", "test")
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
defer os.RemoveAll(tmpdir) // clean up defer os.RemoveAll(tmpdir) // clean up
Expect(f.Unpack(tmpdir, false)).ToNot(HaveOccurred())
Expect(f.Unpack(ctx, tmpdir, false)).ToNot(HaveOccurred())
Expect(fileHelper.Read(filepath.Join(tmpdir, "c"))).To(Equal("c\n")) Expect(fileHelper.Read(filepath.Join(tmpdir, "c"))).To(Equal("c\n"))
Expect(fileHelper.Read(filepath.Join(tmpdir, "cd"))).To(Equal("c\n")) Expect(fileHelper.Read(filepath.Join(tmpdir, "cd"))).To(Equal("c\n"))
os.RemoveAll(f.Path) os.RemoveAll(f.Path)

View File

@ -26,26 +26,27 @@ import (
"strconv" "strconv"
"time" "time"
"github.com/mudler/luet/pkg/api/core/types"
"github.com/mudler/luet/pkg/api/core/types/artifact" "github.com/mudler/luet/pkg/api/core/types/artifact"
. "github.com/mudler/luet/pkg/logger"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/pterm/pterm" "github.com/pterm/pterm"
"github.com/cavaliercoder/grab" "github.com/cavaliercoder/grab"
"github.com/mudler/luet/pkg/config"
) )
type HttpClient struct { type HttpClient struct {
RepoData RepoData RepoData RepoData
Cache *artifact.ArtifactCache Cache *artifact.ArtifactCache
context *types.Context
ProgressBarArea *pterm.AreaPrinter ProgressBarArea *pterm.AreaPrinter
} }
func NewHttpClient(r RepoData) *HttpClient { func NewHttpClient(r RepoData, ctx *types.Context) *HttpClient {
return &HttpClient{ return &HttpClient{
RepoData: r, RepoData: r,
Cache: artifact.NewCache(config.LuetCfg.GetSystem().GetSystemPkgsCacheDirPath()), Cache: artifact.NewCache(ctx.Config.GetSystem().GetSystemPkgsCacheDirPath()),
context: ctx,
} }
} }
@ -96,7 +97,7 @@ func Round(input float64) float64 {
func (c *HttpClient) DownloadFile(p string) (string, error) { func (c *HttpClient) DownloadFile(p string) (string, error) {
var file *os.File = nil var file *os.File = nil
var downloaded bool var downloaded bool
temp, err := config.LuetCfg.GetSystem().TempDir("download") temp, err := c.context.Config.GetSystem().TempDir("download")
if err != nil { if err != nil {
return "", err return "", err
} }
@ -105,13 +106,13 @@ func (c *HttpClient) DownloadFile(p string) (string, error) {
client := NewGrabClient() client := NewGrabClient()
for _, uri := range c.RepoData.Urls { for _, uri := range c.RepoData.Urls {
file, err = config.LuetCfg.GetSystem().TempFile("HttpClient") file, err = c.context.Config.GetSystem().TempFile("HttpClient")
if err != nil { if err != nil {
Debug("Failed downloading", p, "from", uri) c.context.Debug("Failed downloading", p, "from", uri)
continue continue
} }
Debug("Downloading artifact", p, "from", uri) c.context.Debug("Downloading artifact", p, "from", uri)
u, err := url.Parse(uri) u, err := url.Parse(uri)
if err != nil { if err != nil {
@ -143,6 +144,7 @@ func (c *HttpClient) DownloadFile(p string) (string, error) {
//pb.Increment() //pb.Increment()
pb.Increment().Current = int(resp.BytesComplete()) pb.Increment().Current = int(resp.BytesComplete())
case <-resp.Done: case <-resp.Done:
pb.Increment().Current = int(resp.BytesComplete())
// download is complete // download is complete
break download_loop break download_loop
} }
@ -152,7 +154,7 @@ func (c *HttpClient) DownloadFile(p string) (string, error) {
continue continue
} }
Info("Downloaded", p, "of", c.context.Info("Downloaded", p, "of",
fmt.Sprintf("%.2f", (float64(resp.BytesComplete())/1000)/1000), "MB (", fmt.Sprintf("%.2f", (float64(resp.BytesComplete())/1000)/1000), "MB (",
fmt.Sprintf("%.2f", (float64(resp.BytesPerSecond())/1024)/1024), "MiB/s )") fmt.Sprintf("%.2f", (float64(resp.BytesPerSecond())/1024)/1024), "MiB/s )")
pb.Stop() pb.Stop()
@ -175,7 +177,7 @@ func (c *HttpClient) DownloadArtifact(a *artifact.PackageArtifact) (*artifact.Pa
// Check if file is already in cache // Check if file is already in cache
if err == nil { if err == nil {
newart.Path = fileName newart.Path = fileName
Debug("Use artifact", artifactName, "from cache.") c.context.Debug("Use artifact", artifactName, "from cache.")
} else { } else {
d, err := c.DownloadFile(artifactName) d, err := c.DownloadFile(artifactName)
if err != nil { if err != nil {

View File

@ -1,4 +1,4 @@
// Copyright © 2019 Ettore Di Giacinto <mudler@gentoo.org> // Copyright © 2019-2021 Ettore Di Giacinto <mudler@gentoo.org>
// //
// This program is free software; you can redistribute it and/or modify // This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
@ -22,6 +22,7 @@ import (
"os" "os"
"path/filepath" "path/filepath"
"github.com/mudler/luet/pkg/api/core/types"
"github.com/mudler/luet/pkg/api/core/types/artifact" "github.com/mudler/luet/pkg/api/core/types/artifact"
fileHelper "github.com/mudler/luet/pkg/helpers/file" fileHelper "github.com/mudler/luet/pkg/helpers/file"
. "github.com/mudler/luet/pkg/installer/client" . "github.com/mudler/luet/pkg/installer/client"
@ -31,6 +32,7 @@ import (
var _ = Describe("Http client", func() { var _ = Describe("Http client", func() {
Context("With repository", func() { Context("With repository", func() {
ctx := types.NewContext()
It("Downloads single files", func() { It("Downloads single files", func() {
// setup small staticfile webserver with content // setup small staticfile webserver with content
@ -43,7 +45,7 @@ var _ = Describe("Http client", func() {
err = ioutil.WriteFile(filepath.Join(tmpdir, "test.txt"), []byte(`test`), os.ModePerm) err = ioutil.WriteFile(filepath.Join(tmpdir, "test.txt"), []byte(`test`), os.ModePerm)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
c := NewHttpClient(RepoData{Urls: []string{ts.URL}}) c := NewHttpClient(RepoData{Urls: []string{ts.URL}}, ctx)
path, err := c.DownloadFile("test.txt") path, err := c.DownloadFile("test.txt")
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
Expect(fileHelper.Read(path)).To(Equal("test")) Expect(fileHelper.Read(path)).To(Equal("test"))
@ -61,7 +63,7 @@ var _ = Describe("Http client", func() {
err = ioutil.WriteFile(filepath.Join(tmpdir, "test.txt"), []byte(`test`), os.ModePerm) err = ioutil.WriteFile(filepath.Join(tmpdir, "test.txt"), []byte(`test`), os.ModePerm)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
c := NewHttpClient(RepoData{Urls: []string{ts.URL}}) c := NewHttpClient(RepoData{Urls: []string{ts.URL}}, ctx)
path, err := c.DownloadArtifact(&artifact.PackageArtifact{Path: "test.txt"}) path, err := c.DownloadArtifact(&artifact.PackageArtifact{Path: "test.txt"})
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
Expect(fileHelper.Read(path.Path)).To(Equal("test")) Expect(fileHelper.Read(path.Path)).To(Equal("test"))

View File

@ -1,4 +1,4 @@
// Copyright © 2019 Ettore Di Giacinto <mudler@gentoo.org> // Copyright © 2019-2021 Ettore Di Giacinto <mudler@gentoo.org>
// //
// This program is free software; you can redistribute it and/or modify // This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by

View File

@ -1,4 +1,4 @@
// Copyright © 2020-2021 Ettore Di Giacinto <mudler@gentoo.org> // Copyright © 2019-2021 Ettore Di Giacinto <mudler@gentoo.org>
// //
// This program is free software; you can redistribute it and/or modify // This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
@ -20,22 +20,23 @@ import (
"path" "path"
"path/filepath" "path/filepath"
"github.com/mudler/luet/pkg/api/core/types"
"github.com/mudler/luet/pkg/api/core/types/artifact" "github.com/mudler/luet/pkg/api/core/types/artifact"
"github.com/mudler/luet/pkg/config"
fileHelper "github.com/mudler/luet/pkg/helpers/file" fileHelper "github.com/mudler/luet/pkg/helpers/file"
. "github.com/mudler/luet/pkg/logger"
"github.com/pkg/errors" "github.com/pkg/errors"
) )
type LocalClient struct { type LocalClient struct {
RepoData RepoData RepoData RepoData
Cache *artifact.ArtifactCache Cache *artifact.ArtifactCache
context *types.Context
} }
func NewLocalClient(r RepoData) *LocalClient { func NewLocalClient(r RepoData, ctx *types.Context) *LocalClient {
return &LocalClient{ return &LocalClient{
Cache: artifact.NewCache(config.LuetCfg.GetSystem().GetSystemPkgsCacheDirPath()), Cache: artifact.NewCache(ctx.Config.GetSystem().GetSystemPkgsCacheDirPath()),
RepoData: r, RepoData: r,
context: ctx,
} }
} }
@ -49,7 +50,7 @@ func (c *LocalClient) DownloadArtifact(a *artifact.PackageArtifact) (*artifact.P
// Check if file is already in cache // Check if file is already in cache
if err == nil { if err == nil {
newart.Path = fileName newart.Path = fileName
Debug("Use artifact", artifactName, "from cache.") c.context.Debug("Use artifact", artifactName, "from cache.")
} else { } else {
d, err := c.DownloadFile(artifactName) d, err := c.DownloadFile(artifactName)
if err != nil { if err != nil {
@ -69,8 +70,8 @@ func (c *LocalClient) DownloadFile(name string) (string, error) {
rootfs := "" rootfs := ""
if !config.LuetCfg.ConfigFromHost { if !c.context.Config.ConfigFromHost {
rootfs, err = config.LuetCfg.GetSystem().GetRootFsAbs() rootfs, err = c.context.Config.GetSystem().GetRootFsAbs()
if err != nil { if err != nil {
return "", err return "", err
} }
@ -81,8 +82,8 @@ func (c *LocalClient) DownloadFile(name string) (string, error) {
uri = filepath.Join(rootfs, uri) uri = filepath.Join(rootfs, uri)
Info("Downloading file", name, "from", uri) c.context.Info("Copying file", name, "from", uri)
file, err = config.LuetCfg.GetSystem().TempFile("localclient") file, err = c.context.Config.GetSystem().TempFile("localclient")
if err != nil { if err != nil {
continue continue
} }

View File

@ -1,4 +1,4 @@
// Copyright © 2019 Ettore Di Giacinto <mudler@gentoo.org> // Copyright © 2019-2021 Ettore Di Giacinto <mudler@gentoo.org>
// //
// This program is free software; you can redistribute it and/or modify // This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
@ -20,6 +20,7 @@ import (
"os" "os"
"path/filepath" "path/filepath"
"github.com/mudler/luet/pkg/api/core/types"
"github.com/mudler/luet/pkg/api/core/types/artifact" "github.com/mudler/luet/pkg/api/core/types/artifact"
fileHelper "github.com/mudler/luet/pkg/helpers/file" fileHelper "github.com/mudler/luet/pkg/helpers/file"
. "github.com/mudler/luet/pkg/installer/client" . "github.com/mudler/luet/pkg/installer/client"
@ -29,6 +30,8 @@ import (
var _ = Describe("Local client", func() { var _ = Describe("Local client", func() {
Context("With repository", func() { Context("With repository", func() {
ctx := types.NewContext()
It("Downloads single files", func() { It("Downloads single files", func() {
tmpdir, err := ioutil.TempDir("", "test") tmpdir, err := ioutil.TempDir("", "test")
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
@ -38,7 +41,7 @@ var _ = Describe("Local client", func() {
err = ioutil.WriteFile(filepath.Join(tmpdir, "test.txt"), []byte(`test`), os.ModePerm) err = ioutil.WriteFile(filepath.Join(tmpdir, "test.txt"), []byte(`test`), os.ModePerm)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
c := NewLocalClient(RepoData{Urls: []string{tmpdir}}) c := NewLocalClient(RepoData{Urls: []string{tmpdir}}, ctx)
path, err := c.DownloadFile("test.txt") path, err := c.DownloadFile("test.txt")
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
Expect(fileHelper.Read(path)).To(Equal("test")) Expect(fileHelper.Read(path)).To(Equal("test"))
@ -54,7 +57,7 @@ var _ = Describe("Local client", func() {
err = ioutil.WriteFile(filepath.Join(tmpdir, "test.txt"), []byte(`test`), os.ModePerm) err = ioutil.WriteFile(filepath.Join(tmpdir, "test.txt"), []byte(`test`), os.ModePerm)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
c := NewLocalClient(RepoData{Urls: []string{tmpdir}}) c := NewLocalClient(RepoData{Urls: []string{tmpdir}}, ctx)
path, err := c.DownloadArtifact(&artifact.PackageArtifact{Path: "test.txt"}) path, err := c.DownloadArtifact(&artifact.PackageArtifact{Path: "test.txt"})
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
Expect(fileHelper.Read(path.Path)).To(Equal("test")) Expect(fileHelper.Read(path.Path)).To(Equal("test"))

View File

@ -1,100 +0,0 @@
// Copyright © 2019-2020 Ettore Di Giacinto <mudler@gentoo.org>
// Daniele Rondina <geaaru@sabayonlinux.org>
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, see <http://www.gnu.org/licenses/>.
package installer
import (
"io/ioutil"
"path"
"path/filepath"
"regexp"
"github.com/ghodss/yaml"
. "github.com/mudler/luet/pkg/config"
. "github.com/mudler/luet/pkg/logger"
)
func LoadConfigProtectConfs(c *LuetConfig) error {
var regexConfs = regexp.MustCompile(`.yml$`)
var err error
rootfs := ""
// Respect the rootfs param on read repositories
if !c.ConfigFromHost {
rootfs, err = c.GetSystem().GetRootFsAbs()
if err != nil {
return err
}
}
for _, cdir := range c.ConfigProtectConfDir {
cdir = filepath.Join(rootfs, cdir)
Debug("Parsing Config Protect Directory", cdir, "...")
files, err := ioutil.ReadDir(cdir)
if err != nil {
Debug("Skip dir", cdir, ":", err.Error())
continue
}
for _, file := range files {
if file.IsDir() {
continue
}
if !regexConfs.MatchString(file.Name()) {
Debug("File", file.Name(), "skipped.")
continue
}
content, err := ioutil.ReadFile(path.Join(cdir, file.Name()))
if err != nil {
Warning("On read file", file.Name(), ":", err.Error())
Warning("File", file.Name(), "skipped.")
continue
}
r, err := LoadConfigProtectConFile(file.Name(), content)
if err != nil {
Warning("On parse file", file.Name(), ":", err.Error())
Warning("File", file.Name(), "skipped.")
continue
}
if r.Name == "" || len(r.Directories) == 0 {
Warning("Invalid config protect file", file.Name())
Warning("File", file.Name(), "skipped.")
continue
}
c.AddConfigProtectConfFile(r)
}
}
return nil
}
func LoadConfigProtectConFile(filename string, data []byte) (*ConfigProtectConfFile, error) {
ans := NewConfigProtectConfFile(filename)
err := yaml.Unmarshal(data, &ans)
if err != nil {
return nil, err
}
return ans, nil
}

View File

@ -1,4 +1,4 @@
// Copyright © 2019 Ettore Di Giacinto <mudler@gentoo.org> // Copyright © 2019-2021 Ettore Di Giacinto <mudler@gentoo.org>
// //
// This program is free software; you can redistribute it and/or modify // This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
@ -20,9 +20,8 @@ import (
"os/exec" "os/exec"
"github.com/ghodss/yaml" "github.com/ghodss/yaml"
"github.com/mudler/luet/pkg/api/core/types"
box "github.com/mudler/luet/pkg/box" box "github.com/mudler/luet/pkg/box"
. "github.com/mudler/luet/pkg/config"
. "github.com/mudler/luet/pkg/logger"
"github.com/pkg/errors" "github.com/pkg/errors"
) )
@ -33,7 +32,7 @@ type LuetFinalizer struct {
Uninstall []string `json:"uninstall"` // TODO: Where to store? Uninstall []string `json:"uninstall"` // TODO: Where to store?
} }
func (f *LuetFinalizer) RunInstall(s *System) error { func (f *LuetFinalizer) RunInstall(ctx *types.Context, s *System) error {
var cmd string var cmd string
var args []string var args []string
if len(f.Shell) == 0 { if len(f.Shell) == 0 {
@ -49,17 +48,17 @@ func (f *LuetFinalizer) RunInstall(s *System) error {
for _, c := range f.Install { for _, c := range f.Install {
toRun := append(args, c) toRun := append(args, c)
Info(":shell: Executing finalizer on ", s.Target, cmd, toRun) ctx.Info(":shell: Executing finalizer on ", s.Target, cmd, toRun)
if s.Target == string(os.PathSeparator) { if s.Target == string(os.PathSeparator) {
cmd := exec.Command(cmd, toRun...) cmd := exec.Command(cmd, toRun...)
cmd.Env = LuetCfg.GetFinalizerEnvs() cmd.Env = ctx.Config.GetFinalizerEnvs()
stdoutStderr, err := cmd.CombinedOutput() stdoutStderr, err := cmd.CombinedOutput()
if err != nil { if err != nil {
return errors.Wrap(err, "Failed running command: "+string(stdoutStderr)) return errors.Wrap(err, "Failed running command: "+string(stdoutStderr))
} }
Info(string(stdoutStderr)) ctx.Info(string(stdoutStderr))
} else { } else {
b := box.NewBox(cmd, toRun, []string{}, LuetCfg.GetFinalizerEnvs(), s.Target, false, true, true) b := box.NewBox(cmd, toRun, []string{}, ctx.Config.GetFinalizerEnvs(), s.Target, false, true, true)
err := b.Run() err := b.Run()
if err != nil { if err != nil {
return errors.Wrap(err, "Failed running command ") return errors.Wrap(err, "Failed running command ")
@ -70,15 +69,15 @@ func (f *LuetFinalizer) RunInstall(s *System) error {
} }
// TODO: We don't store uninstall finalizers ?! // TODO: We don't store uninstall finalizers ?!
func (f *LuetFinalizer) RunUnInstall() error { func (f *LuetFinalizer) RunUnInstall(ctx *types.Context) error {
for _, c := range f.Uninstall { for _, c := range f.Uninstall {
Debug("finalizer:", "sh", "-c", c) ctx.Debug("finalizer:", "sh", "-c", c)
cmd := exec.Command("sh", "-c", c) cmd := exec.Command("sh", "-c", c)
stdoutStderr, err := cmd.CombinedOutput() stdoutStderr, err := cmd.CombinedOutput()
if err != nil { if err != nil {
return errors.Wrap(err, "Failed running command: "+string(stdoutStderr)) return errors.Wrap(err, "Failed running command: "+string(stdoutStderr))
} }
Info(string(stdoutStderr)) ctx.Info(string(stdoutStderr))
} }
return nil return nil
} }

View File

@ -1,4 +1,4 @@
// Copyright © 2019 Ettore Di Giacinto <mudler@gentoo.org> // Copyright © 2019-2021 Ettore Di Giacinto <mudler@gentoo.org>
// //
// This program is free software; you can redistribute it and/or modify // This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
@ -24,15 +24,15 @@ import (
"strings" "strings"
"sync" "sync"
"github.com/mudler/luet/pkg/api/core/config"
"github.com/mudler/luet/pkg/api/core/types" "github.com/mudler/luet/pkg/api/core/types"
artifact "github.com/mudler/luet/pkg/api/core/types/artifact" artifact "github.com/mudler/luet/pkg/api/core/types/artifact"
"github.com/mudler/luet/pkg/bus" "github.com/mudler/luet/pkg/bus"
"github.com/mudler/luet/pkg/config"
"github.com/mudler/luet/pkg/helpers" "github.com/mudler/luet/pkg/helpers"
fileHelper "github.com/mudler/luet/pkg/helpers/file" fileHelper "github.com/mudler/luet/pkg/helpers/file"
"github.com/mudler/luet/pkg/helpers/match" "github.com/mudler/luet/pkg/helpers/match"
"github.com/mudler/luet/pkg/installer/client" "github.com/mudler/luet/pkg/installer/client"
. "github.com/mudler/luet/pkg/logger"
pkg "github.com/mudler/luet/pkg/package" pkg "github.com/mudler/luet/pkg/package"
"github.com/mudler/luet/pkg/solver" "github.com/mudler/luet/pkg/solver"
"github.com/pterm/pterm" "github.com/pterm/pterm"
@ -41,7 +41,7 @@ import (
) )
type LuetInstallerOptions struct { type LuetInstallerOptions struct {
SolverOptions config.LuetSolverOptions SolverOptions types.LuetSolverOptions
Concurrency int Concurrency int
NoDeps bool NoDeps bool
OnlyDeps bool OnlyDeps bool
@ -54,6 +54,8 @@ type LuetInstallerOptions struct {
DownloadOnly bool DownloadOnly bool
Relaxed bool Relaxed bool
PackageRepositories types.LuetRepositories PackageRepositories types.LuetRepositories
Context *types.Context
} }
type LuetInstaller struct { type LuetInstaller struct {
@ -127,26 +129,26 @@ func (l *LuetInstaller) computeUpgrade(syncedRepos Repositories, s *System) (pkg
// Upgrade upgrades a System based on the Installer options. Returns error in case of failure // Upgrade upgrades a System based on the Installer options. Returns error in case of failure
func (l *LuetInstaller) Upgrade(s *System) error { func (l *LuetInstaller) Upgrade(s *System) error {
l.Options.Context.Screen("Upgrade")
syncedRepos, err := l.SyncRepositories() syncedRepos, err := l.SyncRepositories()
if err != nil { if err != nil {
return err return err
} }
Info(":thinking: Computing upgrade, please hang tight... :zzz:") l.Options.Context.Info(":thinking: Computing upgrade, please hang tight... :zzz:")
if l.Options.UpgradeNewRevisions { if l.Options.UpgradeNewRevisions {
Info(":memo: note: will consider new build revisions while upgrading") l.Options.Context.Info(":memo: note: will consider new build revisions while upgrading")
} }
return l.checkAndUpgrade(syncedRepos, s) return l.checkAndUpgrade(syncedRepos, s)
} }
func (l *LuetInstaller) SyncRepositories() (Repositories, error) { func (l *LuetInstaller) SyncRepositories() (Repositories, error) {
Spinner(32) l.Options.Context.Spinner()
defer SpinnerStop() defer l.Options.Context.SpinnerStop()
syncedRepos := Repositories{} syncedRepos := Repositories{}
for _, r := range SystemRepositories(l.Options.PackageRepositories) { for _, r := range SystemRepositories(l.Options.PackageRepositories) {
repo, err := r.Sync(false) repo, err := r.Sync(l.Options.Context, 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())
} }
@ -204,7 +206,7 @@ func (l *LuetInstaller) computeSwap(o Option, syncedRepos Repositories, toRemove
packs, err := l.computeUninstall(o, systemAfterChanges, toRemove...) packs, err := l.computeUninstall(o, systemAfterChanges, toRemove...)
if err != nil && !o.Force { if err != nil && !o.Force {
Error("Failed computing uninstall for ", packsToList(toRemove)) l.Options.Context.Error("Failed computing uninstall for ", packsToList(toRemove))
return nil, nil, nil, nil, errors.Wrap(err, "computing uninstall "+packsToList(toRemove)) return nil, nil, nil, nil, errors.Wrap(err, "computing uninstall "+packsToList(toRemove))
} }
for _, p := range packs { for _, p := range packs {
@ -230,19 +232,19 @@ func (l *LuetInstaller) swap(o Option, syncedRepos Repositories, toRemove pkg.Pa
if l.Options.Ask { if l.Options.Ask {
// if len(toRemove) > 0 { // if len(toRemove) > 0 {
// Info(":recycle: Packages that are going to be removed from the system:\n ", Yellow(packsToList(toRemove)).BgBlack().String()) // l.Options.Context.Info(":recycle: Packages that are going to be removed from the system:\n ", Yellow(packsToList(toRemove)).BgBlack().String())
// } // }
// if len(match) > 0 { // if len(match) > 0 {
// Info("Packages that are going to be installed in the system:") // l.Options.Context.Info("Packages that are going to be installed in the system:")
// // Info("Packages that are going to be installed in the system: \n ", Green(matchesToList(match)).BgBlack().String()) // // l.Options.Context.Info("Packages that are going to be installed in the system: \n ", Green(matchesToList(match)).BgBlack().String())
// printMatches(match) // printMatches(match)
// } // }
Info(":zap: Proposed version changes to the system:\n ") l.Options.Context.Info(":zap: Proposed version changes to the system:\n ")
printMatchUpgrade(match, toRemove) printMatchUpgrade(match, toRemove)
Info("By going forward, you are also accepting the licenses of the packages that you are going to install in your system.") l.Options.Context.Info("By going forward, you are also accepting the licenses of the packages that you are going to install in your system.")
if Ask() { if l.Options.Context.Ask() {
l.Options.Ask = false // Don't prompt anymore l.Options.Ask = false // Don't prompt anymore
} else { } else {
return errors.New("Aborted by user") return errors.New("Aborted by user")
@ -258,7 +260,7 @@ func (l *LuetInstaller) swap(o Option, syncedRepos Repositories, toRemove pkg.Pa
if !l.Options.Force { if !l.Options.Force {
return errors.Wrap(err, "file conflict found") return errors.Wrap(err, "file conflict found")
} else { } else {
Warning("file conflict found", err.Error()) l.Options.Context.Warning("file conflict found", err.Error())
} }
} }
@ -284,7 +286,7 @@ func (l *LuetInstaller) swap(o Option, syncedRepos Repositories, toRemove pkg.Pa
return errors.Wrap(err, "failed getting package to finalize") return errors.Wrap(err, "failed getting package to finalize")
} }
return s.ExecuteFinalizers(toFinalize) return s.ExecuteFinalizers(l.Options.Context, toFinalize)
} }
type Option struct { type Option struct {
@ -347,17 +349,17 @@ func (l *LuetInstaller) installerOpWorker(i int, wg *sync.WaitGroup, c <-chan in
for p := range c { for p := range c {
if p.Uninstall.Package != nil { if p.Uninstall.Package != nil {
Debug("Replacing package inplace") l.Options.Context.Debug("Replacing package inplace")
toUninstall, uninstall, err := l.generateUninstallFn(p.Uninstall.Option, s, p.Uninstall.Package) toUninstall, uninstall, err := l.generateUninstallFn(p.Uninstall.Option, s, p.Uninstall.Package)
if err != nil { if err != nil {
Error("Failed to generate Uninstall function for" + err.Error()) l.Options.Context.Error("Failed to generate Uninstall function for" + err.Error())
continue continue
//return errors.Wrap(err, "while computing uninstall") //return errors.Wrap(err, "while computing uninstall")
} }
err = uninstall() err = uninstall()
if err != nil { if err != nil {
Error("Failed uninstall for ", packsToList(toUninstall)) l.Options.Context.Error("Failed uninstall for ", packsToList(toUninstall))
continue continue
//return errors.Wrap(err, "uninstalling "+packsToList(toUninstall)) //return errors.Wrap(err, "uninstalling "+packsToList(toUninstall))
} }
@ -377,7 +379,7 @@ func (l *LuetInstaller) installerOpWorker(i int, wg *sync.WaitGroup, c <-chan in
s, s,
) )
if err != nil { if err != nil {
Error(err) l.Options.Context.Error(err)
} }
} }
} }
@ -447,10 +449,10 @@ func (l *LuetInstaller) checkAndUpgrade(r Repositories, s *System) error {
// SpinnerStop() // SpinnerStop()
if len(toInstall) == 0 && len(uninstall) == 0 { if len(toInstall) == 0 && len(uninstall) == 0 {
Info("Nothing to upgrade") l.Options.Context.Info("Nothing to upgrade")
return nil return nil
} else { } else {
Info(":zap: Proposed version changes to the system:\n ") l.Options.Context.Info(":zap: Proposed version changes to the system:\n ")
printUpgradeList(toInstall, uninstall) printUpgradeList(toInstall, uninstall)
} }
@ -471,8 +473,8 @@ func (l *LuetInstaller) checkAndUpgrade(r Repositories, s *System) error {
} }
if l.Options.Ask { if l.Options.Ask {
Info("By going forward, you are also accepting the licenses of the packages that you are going to install in your system.") l.Options.Context.Info("By going forward, you are also accepting the licenses of the packages that you are going to install in your system.")
if Ask() { if l.Options.Context.Ask() {
l.Options.Ask = false // Don't prompt anymore l.Options.Ask = false // Don't prompt anymore
return l.swap(o, r, uninstall, toInstall, s) return l.swap(o, r, uninstall, toInstall, s)
} else { } else {
@ -484,14 +486,14 @@ func (l *LuetInstaller) checkAndUpgrade(r Repositories, s *System) error {
} }
func (l *LuetInstaller) Install(cp pkg.Packages, s *System) error { func (l *LuetInstaller) Install(cp pkg.Packages, s *System) error {
Screen("Install") l.Options.Context.Screen("Install")
syncedRepos, err := l.SyncRepositories() syncedRepos, err := l.SyncRepositories()
if err != nil { if err != nil {
return err return err
} }
if len(s.Database.World()) > 0 && !l.Options.Relaxed { if len(s.Database.World()) > 0 && !l.Options.Relaxed {
Info(":thinking: Checking for available upgrades") l.Options.Context.Info(":thinking: Checking for available upgrades")
if err := l.checkAndUpgrade(syncedRepos, s); err != nil { if err := l.checkAndUpgrade(syncedRepos, s); err != nil {
return errors.Wrap(err, "while checking upgrades before install") return errors.Wrap(err, "while checking upgrades before install")
} }
@ -511,7 +513,7 @@ func (l *LuetInstaller) Install(cp pkg.Packages, s *System) error {
// Check if we have to process something, or return to the user an error // Check if we have to process something, or return to the user an error
if len(match) == 0 { if len(match) == 0 {
Info("No packages to install") l.Options.Context.Info("No packages to install")
return nil return nil
} }
// Resolvers might decide to remove some packages from being installed // Resolvers might decide to remove some packages from being installed
@ -536,18 +538,18 @@ func (l *LuetInstaller) Install(cp pkg.Packages, s *System) error {
} }
if !found { if !found {
return fmt.Errorf("Package '%s' not found", p.HumanReadableString()) return fmt.Errorf("package '%s' not found", p.HumanReadableString())
} }
} }
} }
Info("Packages that are going to be installed in the system:") l.Options.Context.Info("Packages that are going to be installed in the system:")
//Info("Packages that are going to be installed in the system: \n ", Green(matchesToList(match)).BgBlack().String()) //l.Options.Context.Info("Packages that are going to be installed in the system: \n ", Green(matchesToList(match)).BgBlack().String())
printMatches(match) printMatches(match)
if l.Options.Ask { if l.Options.Ask {
Info("By going forward, you are also accepting the licenses of the packages that you are going to install in your system.") l.Options.Context.Info("By going forward, you are also accepting the licenses of the packages that you are going to install in your system.")
if Ask() { if l.Options.Context.Ask() {
l.Options.Ask = false // Don't prompt anymore l.Options.Ask = false // Don't prompt anymore
return l.install(o, syncedRepos, match, packages, assertions, allRepos, s) return l.install(o, syncedRepos, match, packages, assertions, allRepos, s)
} else { } else {
@ -596,7 +598,7 @@ func (l *LuetInstaller) Reclaim(s *System) error {
for _, repo := range syncedRepos { for _, repo := range syncedRepos {
for _, artefact := range repo.GetIndex() { for _, artefact := range repo.GetIndex() {
Debug("Checking if", l.Options.Context.Debug("Checking if",
artefact.CompileSpec.GetPackage().HumanReadableString(), artefact.CompileSpec.GetPackage().HumanReadableString(),
"from", repo.GetName(), "is installed") "from", repo.GetName(), "is installed")
FILES: FILES:
@ -606,7 +608,7 @@ func (l *LuetInstaller) Reclaim(s *System) error {
if err != nil { if err != nil {
return err return err
} }
Info(":mag: Found package:", p.HumanReadableString()) l.Options.Context.Info(":mag: Found package:", p.HumanReadableString())
toMerge = append(toMerge, ArtifactMatch{Artifact: artefact, Package: p}) toMerge = append(toMerge, ArtifactMatch{Artifact: artefact, Package: p})
break FILES break FILES
} }
@ -619,7 +621,7 @@ func (l *LuetInstaller) Reclaim(s *System) error {
vers, _ := s.Database.FindPackageVersions(pack) vers, _ := s.Database.FindPackageVersions(pack)
if len(vers) >= 1 { if len(vers) >= 1 {
Warning("Filtering out package " + pack.HumanReadableString() + ", already reclaimed") l.Options.Context.Warning("Filtering out package " + pack.HumanReadableString() + ", already reclaimed")
continue continue
} }
_, err := s.Database.CreatePackage(pack) _, err := s.Database.CreatePackage(pack)
@ -627,9 +629,9 @@ func (l *LuetInstaller) Reclaim(s *System) error {
return errors.Wrap(err, "Failed creating package") return errors.Wrap(err, "Failed creating package")
} }
s.Database.SetPackageFiles(&pkg.PackageFile{PackageFingerprint: pack.GetFingerPrint(), Files: match.Artifact.Files}) s.Database.SetPackageFiles(&pkg.PackageFile{PackageFingerprint: pack.GetFingerPrint(), Files: match.Artifact.Files})
Info(":zap:Reclaimed package:", pack.HumanReadableString()) l.Options.Context.Info(":zap:Reclaimed package:", pack.HumanReadableString())
} }
Info("Done!") l.Options.Context.Info("Done!")
return nil return nil
} }
@ -645,7 +647,7 @@ func (l *LuetInstaller) computeInstall(o Option, syncedRepos Repositories, cp pk
vers, _ := s.Database.FindPackageVersions(pi) vers, _ := s.Database.FindPackageVersions(pi)
if len(vers) >= 1 { if len(vers) >= 1 {
// Warning("Filtering out package " + pi.HumanReadableString() + ", it has other versions already installed. Uninstall one of them first ") // l.Options.Context.Warning("Filtering out package " + pi.HumanReadableString() + ", it has other versions already installed. Uninstall one of them first ")
continue continue
//return errors.New("Package " + pi.GetFingerPrint() + " has other versions already installed. Uninstall one of them first: " + strings.Join(vers, " ")) //return errors.New("Package " + pi.GetFingerPrint() + " has other versions already installed. Uninstall one of them first: " + strings.Join(vers, " "))
@ -727,7 +729,7 @@ func (l *LuetInstaller) computeInstall(o Option, syncedRepos Repositories, cp pk
func (l *LuetInstaller) getFinalizers(allRepos pkg.PackageDatabase, solution solver.PackagesAssertions, toInstall map[string]ArtifactMatch, nodeps bool) ([]pkg.Package, error) { func (l *LuetInstaller) getFinalizers(allRepos pkg.PackageDatabase, solution solver.PackagesAssertions, toInstall map[string]ArtifactMatch, nodeps bool) ([]pkg.Package, error) {
var toFinalize []pkg.Package var toFinalize []pkg.Package
if !nodeps { if !nodeps {
// TODO: Lower those errors as warning // TODO: Lower those errors as l.Options.Context.Warning
for _, w := range toInstall { for _, w := range toInstall {
// Finalizers needs to run in order and in sequence. // Finalizers needs to run in order and in sequence.
ordered, err := solution.Order(allRepos, w.Package.GetFingerPrint()) ordered, err := solution.Order(allRepos, w.Package.GetFingerPrint())
@ -765,7 +767,7 @@ func (l *LuetInstaller) getFinalizers(allRepos pkg.PackageDatabase, solution sol
} }
func (l *LuetInstaller) checkFileconflicts(toInstall map[string]ArtifactMatch, checkSystem bool, s *System) error { func (l *LuetInstaller) checkFileconflicts(toInstall map[string]ArtifactMatch, checkSystem bool, s *System) error {
Info("Checking for file conflicts..") l.Options.Context.Info("Checking for file conflicts..")
defer s.Clean() // Release memory defer s.Clean() // Release memory
filesToInstall := []string{} filesToInstall := []string{}
@ -819,7 +821,7 @@ func (l *LuetInstaller) install(o Option, syncedRepos Repositories, toInstall ma
if !l.Options.Force { if !l.Options.Force {
return errors.Wrap(err, "file conflict found") return errors.Wrap(err, "file conflict found")
} else { } else {
Warning("file conflict found", err.Error()) l.Options.Context.Warning("file conflict found", err.Error())
} }
} }
} }
@ -862,12 +864,12 @@ func (l *LuetInstaller) install(o Option, syncedRepos Repositories, toInstall ma
return errors.Wrap(err, "failed getting package to finalize") return errors.Wrap(err, "failed getting package to finalize")
} }
return s.ExecuteFinalizers(toFinalize) 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, area *pterm.AreaPrinter) (*artifact.PackageArtifact, error) {
cli := a.Repository.Client() cli := a.Repository.Client(l.Options.Context)
switch v := cli.(type) { switch v := cli.(type) {
case *client.HttpClient: case *client.HttpClient:
@ -898,7 +900,7 @@ func (l *LuetInstaller) installPackage(m ArtifactMatch, s *System) error {
return errors.Wrap(err, "Could not open package archive") return errors.Wrap(err, "Could not open package archive")
} }
err = a.Unpack(s.Target, true) err = a.Unpack(l.Options.Context, s.Target, true)
if err != nil && !l.Options.Force { if err != nil && !l.Options.Force {
return errors.Wrap(err, "Error met while unpacking rootfs") return errors.Wrap(err, "Error met while unpacking rootfs")
} }
@ -915,10 +917,10 @@ func (l *LuetInstaller) downloadWorker(i int, wg *sync.WaitGroup, c <-chan Artif
// TODO: Keep trace of what was added from the tar, and save it into system // TODO: Keep trace of what was added from the tar, and save it into system
_, err := l.downloadPackage(p, area) _, err := l.downloadPackage(p, area)
if err != nil { if err != nil {
Error("Failed downloading package "+p.Package.GetName(), err.Error()) l.Options.Context.Error("Failed downloading package "+p.Package.GetName(), err.Error())
return errors.Wrap(err, "Failed downloading package "+p.Package.GetName()) return errors.Wrap(err, "Failed downloading package "+p.Package.GetName())
} else { } else {
Success(":package: Package ", p.Package.HumanReadableString(), "downloaded") l.Options.Context.Success(":package: Package ", p.Package.HumanReadableString(), "downloaded")
} }
pb.Increment() pb.Increment()
@ -935,26 +937,26 @@ func (l *LuetInstaller) installerWorker(i int, wg *sync.WaitGroup, c <-chan Arti
err := l.installPackage(p, s) err := l.installPackage(p, s)
if err != nil && !l.Options.Force { if err != nil && !l.Options.Force {
//TODO: Uninstall, rollback. //TODO: Uninstall, rollback.
Fatal("Failed installing package "+p.Package.GetName(), err.Error()) l.Options.Context.Fatal("Failed installing package "+p.Package.GetName(), err.Error())
return errors.Wrap(err, "Failed installing package "+p.Package.GetName()) return errors.Wrap(err, "Failed installing package "+p.Package.GetName())
} }
if err == nil { if err == nil {
Info(":package: Package ", p.Package.HumanReadableString(), "installed") l.Options.Context.Info(":package: Package ", p.Package.HumanReadableString(), "installed")
} else if err != nil && l.Options.Force { } else if err != nil && l.Options.Force {
Info(":package: Package ", p.Package.HumanReadableString(), "installed with failures (forced install)") l.Options.Context.Info(":package: Package ", p.Package.HumanReadableString(), "installed with failures (forced install)")
} }
} }
return nil return nil
} }
func checkAndPrunePath(path string) { func checkAndPrunePath(ctx *types.Context, path string) {
// check if now the target path is empty // check if now the target path is empty
targetPath := filepath.Dir(path) targetPath := filepath.Dir(path)
fi, err := os.Lstat(targetPath) fi, err := os.Lstat(targetPath)
if err != nil { if err != nil {
// Warning("Dir not found (it was before?) ", err.Error()) // l.Options.Context.Warning("Dir not found (it was before?) ", err.Error())
return return
} }
@ -962,24 +964,27 @@ func checkAndPrunePath(path string) {
case mode.IsDir(): case mode.IsDir():
files, err := ioutil.ReadDir(targetPath) files, err := ioutil.ReadDir(targetPath)
if err != nil { if err != nil {
Warning("Failed reading folder", targetPath, err.Error()) ctx.Warning("Failed reading folder", targetPath, err.Error())
return
} }
if len(files) != 0 { if len(files) != 0 {
Debug("Preserving not-empty folder", targetPath) ctx.Debug("Preserving not-empty folder", targetPath)
return return
} }
} }
if err = os.Remove(targetPath); err != nil { if err = os.Remove(targetPath); err != nil {
Warning("Failed removing file (maybe not present in the system target anymore ?)", targetPath, err.Error()) ctx.Warning("Failed removing file (maybe not present in the system target anymore ?)", targetPath, err.Error())
} }
} }
// We will try to cleanup every path from the file, if the folders left behind are empty // We will try to cleanup every path from the file, if the folders left behind are empty
func pruneEmptyFilePath(path string) { func pruneEmptyFilePath(ctx *types.Context, path string) {
checkAndPrunePath(path) checkAndPrunePath(ctx, path)
// A path is for e.g. /usr/bin/bar // A path is for e.g. /usr/bin/bar
// we want to create an array as "/usr", "/usr/bin", "/usr/bin/bar" // we want to create an array
// as "/usr", "/usr/bin", "/usr/bin/bar",
// excluding the target (in the case above was /)
paths := strings.Split(path, string(os.PathSeparator)) paths := strings.Split(path, string(os.PathSeparator))
currentPath := filepath.Join(string(os.PathSeparator), paths[0]) currentPath := filepath.Join(string(os.PathSeparator), paths[0])
allPaths := []string{currentPath} allPaths := []string{currentPath}
@ -989,7 +994,7 @@ func pruneEmptyFilePath(path string) {
} }
match.ReverseAny(allPaths) match.ReverseAny(allPaths)
for _, p := range allPaths { for _, p := range allPaths {
checkAndPrunePath(p) checkAndPrunePath(ctx, p)
} }
} }
@ -1002,7 +1007,7 @@ func (l *LuetInstaller) uninstall(p pkg.Package, s *System) error {
return errors.Wrap(err, "Failed getting installed files") return errors.Wrap(err, "Failed getting installed files")
} }
if !config.LuetCfg.ConfigProtectSkip { if !l.Options.Context.Config.ConfigProtectSkip {
if p.HasAnnotation(string(pkg.ConfigProtectAnnnotation)) { if p.HasAnnotation(string(pkg.ConfigProtectAnnnotation)) {
dir, ok := p.GetAnnotations()[string(pkg.ConfigProtectAnnnotation)] dir, ok := p.GetAnnotations()[string(pkg.ConfigProtectAnnnotation)]
@ -1012,7 +1017,7 @@ func (l *LuetInstaller) uninstall(p pkg.Package, s *System) error {
} }
cp = config.NewConfigProtect(annotationDir) cp = config.NewConfigProtect(annotationDir)
cp.Map(files) cp.Map(files, l.Options.Context.Config.GetConfigProtectConfFiles())
} }
toRemove, notPresent := fileHelper.OrderFiles(s.Target, files) toRemove, notPresent := fileHelper.OrderFiles(s.Target, files)
@ -1021,56 +1026,56 @@ func (l *LuetInstaller) uninstall(p pkg.Package, s *System) error {
for _, f := range toRemove { for _, f := range toRemove {
target := filepath.Join(s.Target, f) target := filepath.Join(s.Target, f)
if !config.LuetCfg.ConfigProtectSkip && cp.Protected(f) { if !l.Options.Context.Config.ConfigProtectSkip && cp.Protected(f) {
Debug("Preserving protected file:", f) l.Options.Context.Debug("Preserving protected file:", f)
continue continue
} }
Debug("Removing", target) l.Options.Context.Debug("Removing", target)
if l.Options.PreserveSystemEssentialData && if l.Options.PreserveSystemEssentialData &&
strings.HasPrefix(f, config.LuetCfg.GetSystem().GetSystemPkgsCacheDirPath()) || strings.HasPrefix(f, l.Options.Context.Config.GetSystem().GetSystemPkgsCacheDirPath()) ||
strings.HasPrefix(f, config.LuetCfg.GetSystem().GetSystemRepoDatabaseDirPath()) { strings.HasPrefix(f, l.Options.Context.Config.GetSystem().GetSystemRepoDatabaseDirPath()) {
Warning("Preserve ", f, " which is required by luet ( you have to delete it manually if you really need to)") l.Options.Context.Warning("Preserve ", f, " which is required by luet ( you have to delete it manually if you really need to)")
continue continue
} }
fi, err := os.Lstat(target) fi, err := os.Lstat(target)
if err != nil { if err != nil {
Warning("File not found (it was before?) ", err.Error()) l.Options.Context.Warning("File not found (it was before?) ", err.Error())
continue continue
} }
switch mode := fi.Mode(); { switch mode := fi.Mode(); {
case mode.IsDir(): case mode.IsDir():
files, err := ioutil.ReadDir(target) files, err := ioutil.ReadDir(target)
if err != nil { if err != nil {
Warning("Failed reading folder", target, err.Error()) l.Options.Context.Warning("Failed reading folder", target, err.Error())
} }
if len(files) != 0 { if len(files) != 0 {
Debug("Preserving not-empty folder", target) l.Options.Context.Debug("Preserving not-empty folder", target)
continue continue
} }
} }
if err = os.Remove(target); err != nil { if err = os.Remove(target); err != nil {
Warning("Failed removing file (maybe not present in the system target anymore ?)", target, err.Error()) l.Options.Context.Warning("Failed removing file (maybe not present in the system target anymore ?)", target, err.Error())
} }
pruneEmptyFilePath(target) pruneEmptyFilePath(l.Options.Context, target)
} }
for _, f := range notPresent { for _, f := range notPresent {
target := filepath.Join(s.Target, f) target := filepath.Join(s.Target, f)
if !config.LuetCfg.ConfigProtectSkip && cp.Protected(f) { if !l.Options.Context.Config.ConfigProtectSkip && cp.Protected(f) {
Debug("Preserving protected file:", f) l.Options.Context.Debug("Preserving protected file:", f)
continue continue
} }
if err = os.Remove(target); err != nil { if err = os.Remove(target); err != nil {
Debug("Failed removing file (not present in the system target)", target, err.Error()) l.Options.Context.Debug("Failed removing file (not present in the system target)", target, err.Error())
} }
pruneEmptyFilePath(target) pruneEmptyFilePath(l.Options.Context, target)
} }
err = s.Database.RemovePackageFiles(p) err = s.Database.RemovePackageFiles(p)
@ -1084,7 +1089,7 @@ func (l *LuetInstaller) uninstall(p pkg.Package, s *System) error {
bus.Manager.Publish(bus.EventPackageUnInstall, p) bus.Manager.Publish(bus.EventPackageUnInstall, p)
Info(":recycle: ", p.GetFingerPrint(), "Removed :heavy_check_mark:") l.Options.Context.Info(":recycle: ", p.HumanReadableString(), "Removed :heavy_check_mark:")
return nil return nil
} }
@ -1124,9 +1129,7 @@ func (l *LuetInstaller) computeUninstall(o Option, s *System, packs ...pkg.Packa
} }
} }
for _, p := range solution { toUninstall = append(toUninstall, solution...)
toUninstall = append(toUninstall, p)
}
} else { } else {
toUninstall = append(toUninstall, packs...) toUninstall = append(toUninstall, packs...)
} }
@ -1160,8 +1163,9 @@ func (l *LuetInstaller) generateUninstallFn(o Option, s *System, packs ...pkg.Pa
} }
func (l *LuetInstaller) Uninstall(s *System, packs ...pkg.Package) error { func (l *LuetInstaller) Uninstall(s *System, packs ...pkg.Package) error {
l.Options.Context.Screen("Uninstall")
Spinner(32) l.Options.Context.Spinner()
o := Option{ o := Option{
FullUninstall: l.Options.FullUninstall, FullUninstall: l.Options.FullUninstall,
Force: l.Options.Force, Force: l.Options.Force,
@ -1172,17 +1176,17 @@ func (l *LuetInstaller) Uninstall(s *System, packs ...pkg.Package) error {
if err != nil { if err != nil {
return errors.Wrap(err, "while computing uninstall") return errors.Wrap(err, "while computing uninstall")
} }
SpinnerStop() l.Options.Context.SpinnerStop()
if len(toUninstall) == 0 { if len(toUninstall) == 0 {
Info("Nothing to do") l.Options.Context.Info("Nothing to do")
return nil return nil
} }
if l.Options.Ask { if l.Options.Ask {
Info(":recycle: Packages that are going to be removed from the system:") l.Options.Context.Info(":recycle: Packages that are going to be removed from the system:")
printList(toUninstall) printList(toUninstall)
if Ask() { if l.Options.Context.Ask() {
l.Options.Ask = false // Don't prompt anymore l.Options.Ask = false // Don't prompt anymore
return uninstall() return uninstall()
} else { } else {

View File

@ -18,19 +18,11 @@ package installer_test
import ( import (
"testing" "testing"
. "github.com/mudler/luet/cmd/util"
config "github.com/mudler/luet/pkg/config"
. "github.com/onsi/ginkgo" . "github.com/onsi/ginkgo"
. "github.com/onsi/gomega" . "github.com/onsi/gomega"
) )
func TestInstaller(t *testing.T) { func TestInstaller(t *testing.T) {
RegisterFailHandler(Fail) RegisterFailHandler(Fail)
LoadConfig()
// Set temporary directory for rootfs
config.LuetCfg.GetSystem().Rootfs = "/tmp/luet-root"
// Force dynamic path for packages cache
config.LuetCfg.GetSystem().PkgsCachePath = ""
RunSpecs(t, "Installer Suite") RunSpecs(t, "Installer Suite")
} }

View File

@ -46,11 +46,17 @@ func stubRepo(tmpdir, tree string) (*LuetSystemRepository, error) {
WithPriority(1), WithPriority(1),
WithSource(tmpdir), WithSource(tmpdir),
WithTree(tree), WithTree(tree),
WithContext(types.NewContext()),
WithDatabase(pkg.NewInMemoryDatabase(false)), WithDatabase(pkg.NewInMemoryDatabase(false)),
) )
} }
var _ = Describe("Installer", func() { var _ = Describe("Installer", func() {
ctx := types.NewContext()
BeforeEach(func() {
ctx = types.NewContext()
})
Context("Writes a repository definition", func() { Context("Writes a repository definition", func() {
It("Writes a repo and can install packages from it", func() { It("Writes a repo and can install packages from it", func() {
@ -67,7 +73,7 @@ var _ = Describe("Installer", func() {
Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(3)) Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(3))
c := compiler.NewLuetCompiler(backend.NewSimpleDockerBackend(), c := compiler.NewLuetCompiler(backend.NewSimpleDockerBackend(ctx),
generalRecipe.GetDatabase(), generalRecipe.GetDatabase(),
options.Concurrency(2)) options.Concurrency(2))
@ -109,7 +115,7 @@ var _ = Describe("Installer", func() {
Expect(fileHelper.Exists(spec.Rel("repository.yaml"))).ToNot(BeTrue()) Expect(fileHelper.Exists(spec.Rel("repository.yaml"))).ToNot(BeTrue())
Expect(fileHelper.Exists(spec.Rel(TREE_TARBALL + ".gz"))).ToNot(BeTrue()) Expect(fileHelper.Exists(spec.Rel(TREE_TARBALL + ".gz"))).ToNot(BeTrue())
Expect(fileHelper.Exists(spec.Rel(REPOSITORY_METAFILE + ".tar"))).ToNot(BeTrue()) Expect(fileHelper.Exists(spec.Rel(REPOSITORY_METAFILE + ".tar"))).ToNot(BeTrue())
err = repo.Write(tmpdir, false, false) err = repo.Write(ctx, tmpdir, false, false)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
Expect(fileHelper.Exists(spec.Rel("repository.yaml"))).To(BeTrue()) Expect(fileHelper.Exists(spec.Rel("repository.yaml"))).To(BeTrue())
@ -131,7 +137,7 @@ urls:
`), pkg.NewInMemoryDatabase(false)) `), pkg.NewInMemoryDatabase(false))
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
inst := NewLuetInstaller(LuetInstallerOptions{ inst := NewLuetInstaller(LuetInstallerOptions{
Concurrency: 1, Concurrency: 1, Context: ctx,
PackageRepositories: types.LuetRepositories{*repo2.LuetRepository}, PackageRepositories: types.LuetRepositories{*repo2.LuetRepository},
}) })
Expect(repo.GetUrls()[0]).To(Equal(tmpdir)) Expect(repo.GetUrls()[0]).To(Equal(tmpdir))
@ -185,7 +191,7 @@ urls:
Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(3)) Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(3))
c := compiler.NewLuetCompiler(backend.NewSimpleDockerBackend(), c := compiler.NewLuetCompiler(backend.NewSimpleDockerBackend(ctx),
generalRecipe.GetDatabase(), options.Concurrency(2)) generalRecipe.GetDatabase(), options.Concurrency(2))
spec, err := c.FromPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}) spec, err := c.FromPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"})
@ -231,7 +237,7 @@ urls:
Expect(fileHelper.Exists(spec.Rel("repository.yaml"))).ToNot(BeTrue()) Expect(fileHelper.Exists(spec.Rel("repository.yaml"))).ToNot(BeTrue())
Expect(fileHelper.Exists(spec.Rel(TREE_TARBALL + ".gz"))).ToNot(BeTrue()) Expect(fileHelper.Exists(spec.Rel(TREE_TARBALL + ".gz"))).ToNot(BeTrue())
Expect(fileHelper.Exists(spec.Rel(REPOSITORY_METAFILE + ".tar"))).ToNot(BeTrue()) Expect(fileHelper.Exists(spec.Rel(REPOSITORY_METAFILE + ".tar"))).ToNot(BeTrue())
err = repo.Write(tmpdir, false, false) err = repo.Write(ctx, tmpdir, false, false)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
Expect(fileHelper.Exists(spec.Rel("repository.yaml"))).To(BeTrue()) Expect(fileHelper.Exists(spec.Rel("repository.yaml"))).To(BeTrue())
@ -254,7 +260,7 @@ urls:
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
inst := NewLuetInstaller(LuetInstallerOptions{ inst := NewLuetInstaller(LuetInstallerOptions{
Concurrency: 1, Concurrency: 1, Context: ctx,
PackageRepositories: types.LuetRepositories{*repo2.LuetRepository}, PackageRepositories: types.LuetRepositories{*repo2.LuetRepository},
}) })
Expect(repo.GetUrls()[0]).To(Equal(tmpdir)) Expect(repo.GetUrls()[0]).To(Equal(tmpdir))
@ -308,7 +314,7 @@ urls:
Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(3)) Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(3))
c := compiler.NewLuetCompiler(backend.NewSimpleDockerBackend(), generalRecipe.GetDatabase(), c := compiler.NewLuetCompiler(backend.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase(),
options.Concurrency(2)) options.Concurrency(2))
spec, err := c.FromPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}) spec, err := c.FromPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"})
@ -358,7 +364,7 @@ urls:
Expect(fileHelper.Exists(spec.Rel("repository.yaml"))).ToNot(BeTrue()) Expect(fileHelper.Exists(spec.Rel("repository.yaml"))).ToNot(BeTrue())
Expect(fileHelper.Exists(spec.Rel(TREE_TARBALL + ".gz"))).ToNot(BeTrue()) Expect(fileHelper.Exists(spec.Rel(TREE_TARBALL + ".gz"))).ToNot(BeTrue())
Expect(fileHelper.Exists(spec.Rel(REPOSITORY_METAFILE + ".tar"))).ToNot(BeTrue()) Expect(fileHelper.Exists(spec.Rel(REPOSITORY_METAFILE + ".tar"))).ToNot(BeTrue())
err = repo.Write(tmpdir, false, false) err = repo.Write(ctx, tmpdir, false, false)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
Expect(fileHelper.Exists(spec.Rel("repository.yaml"))).To(BeTrue()) Expect(fileHelper.Exists(spec.Rel("repository.yaml"))).To(BeTrue())
@ -380,7 +386,7 @@ urls:
`), pkg.NewInMemoryDatabase(false)) `), pkg.NewInMemoryDatabase(false))
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
inst := NewLuetInstaller(LuetInstallerOptions{ inst := NewLuetInstaller(LuetInstallerOptions{
Concurrency: 1, Concurrency: 1, Context: ctx,
PackageRepositories: types.LuetRepositories{*repo2.LuetRepository}, PackageRepositories: types.LuetRepositories{*repo2.LuetRepository},
}) })
Expect(repo.GetUrls()[0]).To(Equal(tmpdir)) Expect(repo.GetUrls()[0]).To(Equal(tmpdir))
@ -437,7 +443,7 @@ urls:
Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(3)) Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(3))
c := compiler.NewLuetCompiler(backend.NewSimpleDockerBackend(), generalRecipe.GetDatabase(), c := compiler.NewLuetCompiler(backend.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase(),
options.Concurrency(2)) options.Concurrency(2))
spec, err := c.FromPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}) spec, err := c.FromPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"})
@ -487,7 +493,7 @@ urls:
Expect(fileHelper.Exists(spec.Rel("repository.yaml"))).ToNot(BeTrue()) Expect(fileHelper.Exists(spec.Rel("repository.yaml"))).ToNot(BeTrue())
Expect(fileHelper.Exists(spec.Rel(TREE_TARBALL + ".gz"))).ToNot(BeTrue()) Expect(fileHelper.Exists(spec.Rel(TREE_TARBALL + ".gz"))).ToNot(BeTrue())
Expect(fileHelper.Exists(spec.Rel(REPOSITORY_METAFILE + ".tar"))).ToNot(BeTrue()) Expect(fileHelper.Exists(spec.Rel(REPOSITORY_METAFILE + ".tar"))).ToNot(BeTrue())
err = repo.Write(tmpdir, false, false) err = repo.Write(ctx, tmpdir, false, false)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
Expect(fileHelper.Exists(spec.Rel("repository.yaml"))).To(BeTrue()) Expect(fileHelper.Exists(spec.Rel("repository.yaml"))).To(BeTrue())
@ -510,7 +516,7 @@ urls:
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
inst := NewLuetInstaller(LuetInstallerOptions{ inst := NewLuetInstaller(LuetInstallerOptions{
Concurrency: 1, Concurrency: 1, Context: ctx,
PackageRepositories: types.LuetRepositories{*repo2.LuetRepository}, PackageRepositories: types.LuetRepositories{*repo2.LuetRepository},
}) })
Expect(repo.GetUrls()[0]).To(Equal(tmpdir)) Expect(repo.GetUrls()[0]).To(Equal(tmpdir))
@ -536,7 +542,7 @@ urls:
Expect(len(generalRecipe2.GetDatabase().GetPackages())).To(Equal(1)) Expect(len(generalRecipe2.GetDatabase().GetPackages())).To(Equal(1))
c = compiler.NewLuetCompiler(backend.NewSimpleDockerBackend(), generalRecipe2.GetDatabase(), options.Concurrency(2)) c = compiler.NewLuetCompiler(backend.NewSimpleDockerBackend(ctx), generalRecipe2.GetDatabase(), options.Concurrency(2))
spec, err = c.FromPackage(&pkg.DefaultPackage{Name: "alpine", Category: "seed", Version: "1.0"}) spec, err = c.FromPackage(&pkg.DefaultPackage{Name: "alpine", Category: "seed", Version: "1.0"})
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
@ -551,7 +557,7 @@ urls:
repo, err = stubRepo(tmpdir2, "../../tests/fixtures/alpine") repo, err = stubRepo(tmpdir2, "../../tests/fixtures/alpine")
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
err = repo.Write(tmpdir2, false, false) err = repo.Write(ctx, tmpdir2, false, false)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
fakeroot, err = ioutil.TempDir("", "fakeroot") fakeroot, err = ioutil.TempDir("", "fakeroot")
@ -567,7 +573,7 @@ urls:
`), pkg.NewInMemoryDatabase(false)) `), pkg.NewInMemoryDatabase(false))
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
inst = NewLuetInstaller(LuetInstallerOptions{ inst = NewLuetInstaller(LuetInstallerOptions{
Concurrency: 1, Concurrency: 1, Context: ctx,
PackageRepositories: types.LuetRepositories{*repo2.LuetRepository}, PackageRepositories: types.LuetRepositories{*repo2.LuetRepository},
}) })
Expect(repo.GetUrls()[0]).To(Equal(tmpdir2)) Expect(repo.GetUrls()[0]).To(Equal(tmpdir2))
@ -597,7 +603,7 @@ urls:
Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(4)) Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(4))
c := compiler.NewLuetCompiler(backend.NewSimpleDockerBackend(), generalRecipe.GetDatabase(), options.Concurrency(2)) c := compiler.NewLuetCompiler(backend.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase(), options.Concurrency(2))
spec, err := c.FromPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}) spec, err := c.FromPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"})
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
@ -626,7 +632,7 @@ urls:
Expect(fileHelper.Exists(spec.Rel("repository.yaml"))).ToNot(BeTrue()) Expect(fileHelper.Exists(spec.Rel("repository.yaml"))).ToNot(BeTrue())
Expect(fileHelper.Exists(spec.Rel(TREE_TARBALL + ".gz"))).ToNot(BeTrue()) Expect(fileHelper.Exists(spec.Rel(TREE_TARBALL + ".gz"))).ToNot(BeTrue())
Expect(fileHelper.Exists(spec.Rel(REPOSITORY_METAFILE + ".tar"))).ToNot(BeTrue()) Expect(fileHelper.Exists(spec.Rel(REPOSITORY_METAFILE + ".tar"))).ToNot(BeTrue())
err = repo.Write(tmpdir, false, false) err = repo.Write(ctx, tmpdir, false, false)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
Expect(fileHelper.Exists(spec.Rel("repository.yaml"))).To(BeTrue()) Expect(fileHelper.Exists(spec.Rel("repository.yaml"))).To(BeTrue())
@ -648,7 +654,7 @@ urls:
`), pkg.NewInMemoryDatabase(false)) `), pkg.NewInMemoryDatabase(false))
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
inst := NewLuetInstaller(LuetInstallerOptions{ inst := NewLuetInstaller(LuetInstallerOptions{
Concurrency: 1, Concurrency: 1, Context: ctx,
PackageRepositories: types.LuetRepositories{*repo2.LuetRepository}, PackageRepositories: types.LuetRepositories{*repo2.LuetRepository},
}) })
Expect(repo.GetUrls()[0]).To(Equal(tmpdir)) Expect(repo.GetUrls()[0]).To(Equal(tmpdir))
@ -716,8 +722,8 @@ urls:
Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(3)) Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(3))
Expect(len(generalRecipeNewRepo.GetDatabase().GetPackages())).To(Equal(3)) Expect(len(generalRecipeNewRepo.GetDatabase().GetPackages())).To(Equal(3))
c := compiler.NewLuetCompiler(backend.NewSimpleDockerBackend(), generalRecipe.GetDatabase(), options.Concurrency(2)) c := compiler.NewLuetCompiler(backend.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase(), options.Concurrency(2))
c2 := compiler.NewLuetCompiler(backend.NewSimpleDockerBackend(), generalRecipeNewRepo.GetDatabase()) c2 := compiler.NewLuetCompiler(backend.NewSimpleDockerBackend(ctx), generalRecipeNewRepo.GetDatabase())
spec, err := c.FromPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}) spec, err := c.FromPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"})
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
@ -753,12 +759,12 @@ urls:
Expect(fileHelper.Exists(spec.Rel("repository.yaml"))).ToNot(BeTrue()) Expect(fileHelper.Exists(spec.Rel("repository.yaml"))).ToNot(BeTrue())
Expect(fileHelper.Exists(spec.Rel(TREE_TARBALL + ".gz"))).ToNot(BeTrue()) Expect(fileHelper.Exists(spec.Rel(TREE_TARBALL + ".gz"))).ToNot(BeTrue())
Expect(fileHelper.Exists(spec.Rel(REPOSITORY_METAFILE + ".tar"))).ToNot(BeTrue()) Expect(fileHelper.Exists(spec.Rel(REPOSITORY_METAFILE + ".tar"))).ToNot(BeTrue())
err = repo.Write(tmpdir, false, false) err = repo.Write(ctx, tmpdir, false, false)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
repoupgrade, err := stubRepo(tmpdirnewrepo, "../../tests/fixtures/upgrade_new_repo") repoupgrade, err := stubRepo(tmpdirnewrepo, "../../tests/fixtures/upgrade_new_repo")
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
err = repoupgrade.Write(tmpdirnewrepo, false, false) err = repoupgrade.Write(ctx, tmpdirnewrepo, false, false)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
fakeroot, err := ioutil.TempDir("", "fakeroot") fakeroot, err := ioutil.TempDir("", "fakeroot")
@ -783,7 +789,7 @@ urls:
`), pkg.NewInMemoryDatabase(false)) `), pkg.NewInMemoryDatabase(false))
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
inst := NewLuetInstaller(LuetInstallerOptions{ inst := NewLuetInstaller(LuetInstallerOptions{
Concurrency: 1, Concurrency: 1, Context: ctx,
PackageRepositories: types.LuetRepositories{*repo2.LuetRepository}, PackageRepositories: types.LuetRepositories{*repo2.LuetRepository},
}) })
Expect(repo.GetUrls()[0]).To(Equal(tmpdir)) Expect(repo.GetUrls()[0]).To(Equal(tmpdir))
@ -852,7 +858,7 @@ urls:
Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(4)) Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(4))
c := compiler.NewLuetCompiler( c := compiler.NewLuetCompiler(
backend.NewSimpleDockerBackend(), backend.NewSimpleDockerBackend(ctx),
generalRecipe.GetDatabase(), generalRecipe.GetDatabase(),
options.Concurrency(2), options.Concurrency(2),
options.WithCompressionType(compression.GZip), options.WithCompressionType(compression.GZip),
@ -884,7 +890,7 @@ urls:
Expect(fileHelper.Exists(spec.Rel("repository.yaml"))).ToNot(BeTrue()) Expect(fileHelper.Exists(spec.Rel("repository.yaml"))).ToNot(BeTrue())
Expect(fileHelper.Exists(spec.Rel(TREE_TARBALL + ".gz"))).ToNot(BeTrue()) Expect(fileHelper.Exists(spec.Rel(TREE_TARBALL + ".gz"))).ToNot(BeTrue())
Expect(fileHelper.Exists(spec.Rel(REPOSITORY_METAFILE + ".tar"))).ToNot(BeTrue()) Expect(fileHelper.Exists(spec.Rel(REPOSITORY_METAFILE + ".tar"))).ToNot(BeTrue())
err = repo.Write(tmpdir, false, false) err = repo.Write(ctx, tmpdir, false, false)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
Expect(fileHelper.Exists(spec.Rel("b-test-1.1.package.tar.gz"))).To(BeTrue()) Expect(fileHelper.Exists(spec.Rel("b-test-1.1.package.tar.gz"))).To(BeTrue())
Expect(fileHelper.Exists(spec.Rel("b-test-1.1.package.tar"))).ToNot(BeTrue()) Expect(fileHelper.Exists(spec.Rel("b-test-1.1.package.tar"))).ToNot(BeTrue())
@ -909,7 +915,7 @@ urls:
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
inst := NewLuetInstaller(LuetInstallerOptions{ inst := NewLuetInstaller(LuetInstallerOptions{
Concurrency: 1, Concurrency: 1, Context: ctx,
PackageRepositories: types.LuetRepositories{*repo2.LuetRepository}, PackageRepositories: types.LuetRepositories{*repo2.LuetRepository},
}) })
@ -974,7 +980,7 @@ urls:
systemDB := pkg.NewBoltDatabase(filepath.Join(bolt, "db.db")) systemDB := pkg.NewBoltDatabase(filepath.Join(bolt, "db.db"))
system := &System{Database: systemDB, Target: fakeroot} system := &System{Database: systemDB, Target: fakeroot}
inst := NewLuetInstaller(LuetInstallerOptions{Concurrency: 1, CheckConflicts: true}) inst := NewLuetInstaller(LuetInstallerOptions{Concurrency: 1, Context: ctx, CheckConflicts: true})
D := pkg.NewPackage("D", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) D := pkg.NewPackage("D", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{})
B := pkg.NewPackage("calamares", "", []*pkg.DefaultPackage{D}, []*pkg.DefaultPackage{}) B := pkg.NewPackage("calamares", "", []*pkg.DefaultPackage{D}, []*pkg.DefaultPackage{})
@ -1017,7 +1023,7 @@ urls:
Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(4)) Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(4))
c := compiler.NewLuetCompiler(backend.NewSimpleDockerBackend(), generalRecipe.GetDatabase(), c := compiler.NewLuetCompiler(backend.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase(),
options.Concurrency(2), options.Concurrency(2),
options.WithCompressionType(compression.GZip)) options.WithCompressionType(compression.GZip))
@ -1046,7 +1052,7 @@ urls:
Expect(fileHelper.Exists(spec.Rel("repository.yaml"))).ToNot(BeTrue()) Expect(fileHelper.Exists(spec.Rel("repository.yaml"))).ToNot(BeTrue())
Expect(fileHelper.Exists(spec.Rel(TREE_TARBALL + ".gz"))).ToNot(BeTrue()) Expect(fileHelper.Exists(spec.Rel(TREE_TARBALL + ".gz"))).ToNot(BeTrue())
Expect(fileHelper.Exists(spec.Rel(REPOSITORY_METAFILE + ".tar"))).ToNot(BeTrue()) Expect(fileHelper.Exists(spec.Rel(REPOSITORY_METAFILE + ".tar"))).ToNot(BeTrue())
err = repo.Write(tmpdir, false, false) err = repo.Write(ctx, tmpdir, false, false)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
Expect(fileHelper.Exists(spec.Rel("b-test-1.1.package.tar.gz"))).To(BeTrue()) Expect(fileHelper.Exists(spec.Rel("b-test-1.1.package.tar.gz"))).To(BeTrue())
Expect(fileHelper.Exists(spec.Rel("b-test-1.1.package.tar"))).ToNot(BeTrue()) Expect(fileHelper.Exists(spec.Rel("b-test-1.1.package.tar"))).ToNot(BeTrue())
@ -1071,7 +1077,7 @@ urls:
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
inst := NewLuetInstaller(LuetInstallerOptions{ inst := NewLuetInstaller(LuetInstallerOptions{
Concurrency: 1, Concurrency: 1, Context: ctx,
PackageRepositories: types.LuetRepositories{*repo2.LuetRepository}, PackageRepositories: types.LuetRepositories{*repo2.LuetRepository},
}) })
@ -1126,7 +1132,7 @@ urls:
Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(3)) Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(3))
c := compiler.NewLuetCompiler(backend.NewSimpleDockerBackend(), generalRecipe.GetDatabase(), c := compiler.NewLuetCompiler(backend.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase(),
options.WithCompressionType(compression.GZip)) options.WithCompressionType(compression.GZip))
spec, err := c.FromPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}) spec, err := c.FromPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"})
@ -1151,7 +1157,7 @@ urls:
Expect(fileHelper.Exists(spec.Rel("repository.yaml"))).ToNot(BeTrue()) Expect(fileHelper.Exists(spec.Rel("repository.yaml"))).ToNot(BeTrue())
Expect(fileHelper.Exists(spec.Rel(TREE_TARBALL + ".gz"))).ToNot(BeTrue()) Expect(fileHelper.Exists(spec.Rel(TREE_TARBALL + ".gz"))).ToNot(BeTrue())
Expect(fileHelper.Exists(spec.Rel(REPOSITORY_METAFILE + ".tar"))).ToNot(BeTrue()) Expect(fileHelper.Exists(spec.Rel(REPOSITORY_METAFILE + ".tar"))).ToNot(BeTrue())
err = repo.Write(tmpdir, false, false) err = repo.Write(ctx, tmpdir, false, false)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
Expect(fileHelper.Exists(spec.Rel("repository.yaml"))).To(BeTrue()) Expect(fileHelper.Exists(spec.Rel("repository.yaml"))).To(BeTrue())
@ -1174,7 +1180,7 @@ urls:
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
inst := NewLuetInstaller(LuetInstallerOptions{ inst := NewLuetInstaller(LuetInstallerOptions{
Concurrency: 1, Concurrency: 1, Context: ctx,
PackageRepositories: types.LuetRepositories{*repo2.LuetRepository}, PackageRepositories: types.LuetRepositories{*repo2.LuetRepository},
}) })
@ -1221,7 +1227,7 @@ urls:
Expect(len(generalRecipe2.GetDatabase().GetPackages())).To(Equal(3)) Expect(len(generalRecipe2.GetDatabase().GetPackages())).To(Equal(3))
c = compiler.NewLuetCompiler(backend.NewSimpleDockerBackend(), generalRecipe2.GetDatabase()) c = compiler.NewLuetCompiler(backend.NewSimpleDockerBackend(ctx), generalRecipe2.GetDatabase())
spec, err = c.FromPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.1"}) spec, err = c.FromPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.1"})
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
@ -1238,7 +1244,7 @@ urls:
repo, err = stubRepo(tmpdir2, "../../tests/fixtures/upgrade_new_repo") repo, err = stubRepo(tmpdir2, "../../tests/fixtures/upgrade_new_repo")
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
Expect(repo.GetName()).To(Equal("test")) Expect(repo.GetName()).To(Equal("test"))
err = repo.Write(tmpdir2, false, false) err = repo.Write(ctx, tmpdir2, false, false)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
repo2, err = NewLuetSystemRepositoryFromYaml([]byte(` repo2, err = NewLuetSystemRepositoryFromYaml([]byte(`
@ -1251,7 +1257,7 @@ urls:
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
inst = NewLuetInstaller(LuetInstallerOptions{ inst = NewLuetInstaller(LuetInstallerOptions{
Concurrency: 1, Concurrency: 1, Context: ctx,
PackageRepositories: types.LuetRepositories{*repo2.LuetRepository}, PackageRepositories: types.LuetRepositories{*repo2.LuetRepository},
}) })

View File

@ -1,4 +1,4 @@
// Copyright © 2019 Ettore Di Giacinto <mudler@gentoo.org> // Copyright © 2019-2021 Ettore Di Giacinto <mudler@gentoo.org>
// //
// This program is free software; you can redistribute it and/or modify // This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
@ -34,9 +34,7 @@ import (
"github.com/mudler/luet/pkg/api/core/types" "github.com/mudler/luet/pkg/api/core/types"
"github.com/mudler/luet/pkg/compiler" "github.com/mudler/luet/pkg/compiler"
"github.com/mudler/luet/pkg/config"
"github.com/mudler/luet/pkg/installer/client" "github.com/mudler/luet/pkg/installer/client"
. "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"
@ -117,15 +115,15 @@ func SystemRepositories(t types.LuetRepositories) Repositories {
} }
// LoadBuildTree loads to the tree the compilation specs from the system repositories // LoadBuildTree loads to the tree the compilation specs from the system repositories
func LoadBuildTree(t tree.Builder, db pkg.PackageDatabase, c *config.LuetConfig) error { func LoadBuildTree(t tree.Builder, db pkg.PackageDatabase, ctx *types.Context) error {
var reserr error var reserr error
repos := SystemRepositories(c.SystemRepositories) repos := SystemRepositories(ctx.Config.SystemRepositories)
for _, r := range repos { for _, r := range repos {
repodir, err := config.LuetCfg.GetSystem().TempDir(r.Name) repodir, err := ctx.Config.GetSystem().TempDir(r.Name)
if err != nil { if err != nil {
reserr = multierr.Append(reserr, err) reserr = multierr.Append(reserr, err)
} }
if err := r.SyncBuildMetadata(repodir); err != nil { if err := r.SyncBuildMetadata(ctx, repodir); err != nil {
reserr = multierr.Append(reserr, err) reserr = multierr.Append(reserr, err)
} }
@ -279,12 +277,12 @@ func GenerateRepository(p ...RepositoryOption) (*LuetSystemRepository, error) {
generalRecipe := tree.NewCompilerRecipe(repodb) generalRecipe := tree.NewCompilerRecipe(repodb)
if c.FromRepository { if c.FromRepository {
if err := LoadBuildTree(generalRecipe, repodb, c.config); err != nil { if err := LoadBuildTree(generalRecipe, repodb, c.context); err != nil {
Warning("errors while loading trees from repositories", err.Error()) c.context.Warning("errors while loading trees from repositories", err.Error())
} }
if err := repodb.Clone(tempTree); err != nil { if err := repodb.Clone(tempTree); err != nil {
Warning("errors while cloning trees from repositories", err.Error()) c.context.Warning("errors while cloning trees from repositories", err.Error())
} }
} }
@ -317,7 +315,7 @@ func GenerateRepository(p ...RepositoryOption) (*LuetSystemRepository, error) {
return nil return nil
} }
if _, err := runtimeTree.FindPackage(art.CompileSpec.Package); err != nil && art.CompileSpec.Package.Name != "" { if _, err := runtimeTree.FindPackage(art.CompileSpec.Package); err != nil && art.CompileSpec.Package.Name != "" {
Debug("Adding", art.CompileSpec.Package.HumanReadableString(), "from metadata file", currentpath) c.context.Debug("Adding", art.CompileSpec.Package.HumanReadableString(), "from metadata file", currentpath)
if art.Runtime != nil && art.Runtime.Name != "" { if art.Runtime != nil && art.Runtime.Name != "" {
runtimeTree.CreatePackage(art.Runtime) runtimeTree.CreatePackage(art.Runtime)
} else { } else {
@ -350,7 +348,7 @@ func GenerateRepository(p ...RepositoryOption) (*LuetSystemRepository, error) {
imagePrefix: c.ImagePrefix, imagePrefix: c.ImagePrefix,
} }
if err := repo.initialize(c.Src); err != nil { if err := repo.initialize(c.context, c.Src); err != nil {
return nil, errors.Wrap(err, "while building repository artifact index") return nil, errors.Wrap(err, "while building repository artifact index")
} }
@ -380,8 +378,8 @@ func (r *LuetSystemRepository) SetPriority(n int) {
r.LuetRepository.Priority = n r.LuetRepository.Priority = n
} }
func (r *LuetSystemRepository) initialize(src string) error { func (r *LuetSystemRepository) initialize(ctx *types.Context, src string) error {
generator, err := r.getGenerator() generator, err := r.getGenerator(ctx)
if err != nil { if err != nil {
return errors.Wrap(err, "while constructing repository generator") return errors.Wrap(err, "while constructing repository generator")
} }
@ -523,12 +521,12 @@ func (r *LuetSystemRepository) BumpRevision(repospec string, resetRevision bool)
// AddMetadata adds the repository serialized content into the metadata key of the repository // AddMetadata adds the repository serialized content into the metadata key of the repository
// It writes the serialized content to repospec, and writes the repository.meta.yaml file into dst // It writes the serialized content to repospec, and writes the repository.meta.yaml file into dst
func (r *LuetSystemRepository) AddMetadata(repospec, dst string) (*artifact.PackageArtifact, error) { func (r *LuetSystemRepository) AddMetadata(ctx *types.Context, repospec, dst string) (*artifact.PackageArtifact, error) {
// Create Metadata struct and serialized repository // Create Metadata struct and serialized repository
meta, serialized := r.Serialize() meta, serialized := r.Serialize()
// Create metadata file and repository file // Create metadata file and repository file
metaTmpDir, err := config.LuetCfg.GetSystem().TempDir("metadata") metaTmpDir, err := ctx.Config.GetSystem().TempDir("metadata")
defer os.RemoveAll(metaTmpDir) // clean up defer os.RemoveAll(metaTmpDir) // clean up
if err != nil { if err != nil {
return nil, errors.Wrap(err, "Error met while creating tempdir for metadata") return nil, errors.Wrap(err, "Error met while creating tempdir for metadata")
@ -560,9 +558,9 @@ func (r *LuetSystemRepository) AddMetadata(repospec, dst string) (*artifact.Pack
// AddTree adds a tree.Builder with the given key to the repository. // 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 will generate an artifact which will be then embedded in the repository manifest
// It returns the generated artifacts and an error // It returns the generated artifacts and an error
func (r *LuetSystemRepository) AddTree(t tree.Builder, dst, key string, f LuetRepositoryFile) (*artifact.PackageArtifact, error) { func (r *LuetSystemRepository) AddTree(ctx *types.Context, t tree.Builder, dst, key string, f LuetRepositoryFile) (*artifact.PackageArtifact, error) {
// Create tree and repository file // Create tree and repository file
archive, err := config.LuetCfg.GetSystem().TempDir("archive") archive, err := ctx.Config.GetSystem().TempDir("archive")
if err != nil { if err != nil {
return nil, errors.Wrap(err, "Error met while creating tempdir for archive") return nil, errors.Wrap(err, "Error met while creating tempdir for archive")
} }
@ -649,17 +647,18 @@ type RepositoryGenerator interface {
Initialize(string, pkg.PackageDatabase) ([]*artifact.PackageArtifact, error) Initialize(string, pkg.PackageDatabase) ([]*artifact.PackageArtifact, error)
} }
func (r *LuetSystemRepository) getGenerator() (RepositoryGenerator, error) { func (r *LuetSystemRepository) getGenerator(ctx *types.Context) (RepositoryGenerator, error) {
var rg RepositoryGenerator var rg RepositoryGenerator
switch r.GetType() { switch r.GetType() {
case DiskRepositoryType, HttpRepositoryType: case DiskRepositoryType, HttpRepositoryType:
rg = &localRepositoryGenerator{} rg = &localRepositoryGenerator{context: ctx}
case DockerRepositoryType: case DockerRepositoryType:
rg = &dockerRepositoryGenerator{ rg = &dockerRepositoryGenerator{
b: r.Backend, b: r.Backend,
imagePrefix: r.imagePrefix, imagePrefix: r.imagePrefix,
imagePush: r.PushImages, imagePush: r.PushImages,
force: r.ForcePush, force: r.ForcePush,
context: ctx,
} }
default: default:
return nil, errors.New("invalid repository type") return nil, errors.New("invalid repository type")
@ -668,8 +667,8 @@ func (r *LuetSystemRepository) getGenerator() (RepositoryGenerator, error) {
} }
// Write writes the repository metadata to the supplied destination // Write writes the repository metadata to the supplied destination
func (r *LuetSystemRepository) Write(dst string, resetRevision, force bool) error { func (r *LuetSystemRepository) Write(ctx *types.Context, dst string, resetRevision, force bool) error {
rg, err := r.getGenerator() rg, err := r.getGenerator(ctx)
if err != nil { if err != nil {
return err return err
} }
@ -677,16 +676,16 @@ func (r *LuetSystemRepository) Write(dst string, resetRevision, force bool) erro
return rg.Generate(r, dst, resetRevision) return rg.Generate(r, dst, resetRevision)
} }
func (r *LuetSystemRepository) Client() Client { func (r *LuetSystemRepository) Client(ctx *types.Context) Client {
switch r.GetType() { switch r.GetType() {
case DiskRepositoryType: case DiskRepositoryType:
return client.NewLocalClient(client.RepoData{Urls: r.GetUrls()}) return client.NewLocalClient(client.RepoData{Urls: r.GetUrls()}, ctx)
case HttpRepositoryType: case HttpRepositoryType:
return client.NewHttpClient( return client.NewHttpClient(
client.RepoData{ client.RepoData{
Urls: r.GetUrls(), Urls: r.GetUrls(),
Authentication: r.GetAuthentication(), Authentication: r.GetAuthentication(),
}) }, ctx)
case DockerRepositoryType: case DockerRepositoryType:
return client.NewDockerClient( return client.NewDockerClient(
@ -694,7 +693,7 @@ func (r *LuetSystemRepository) Client() Client {
Urls: r.GetUrls(), Urls: r.GetUrls(),
Authentication: r.GetAuthentication(), Authentication: r.GetAuthentication(),
Verify: r.Verify, Verify: r.Verify,
}) }, ctx)
} }
return nil return nil
} }
@ -736,14 +735,14 @@ func (r *LuetSystemRepository) getRepoFile(c Client, key string) (*artifact.Pack
} }
func (r *LuetSystemRepository) SyncBuildMetadata(path string) error { func (r *LuetSystemRepository) SyncBuildMetadata(ctx *types.Context, path string) error {
repo, err := r.Sync(false) repo, err := r.Sync(ctx, false)
if err != nil { if err != nil {
return errors.Wrap(err, "while syncronizing repository") return errors.Wrap(err, "while syncronizing repository")
} }
c := repo.Client() c := repo.Client(ctx)
if c == nil { if c == nil {
return errors.New("no client could be generated from repository") return errors.New("no client could be generated from repository")
} }
@ -755,7 +754,7 @@ func (r *LuetSystemRepository) SyncBuildMetadata(path string) error {
defer os.RemoveAll(a.Path) defer os.RemoveAll(a.Path)
if err := a.Unpack(filepath.Join(path, "tree"), false); err != nil { if err := a.Unpack(ctx, filepath.Join(path, "tree"), false); err != nil {
return errors.Wrapf(err, "while unpacking: %s", REPOFILE_COMPILER_TREE_KEY) return errors.Wrapf(err, "while unpacking: %s", REPOFILE_COMPILER_TREE_KEY)
} }
@ -773,13 +772,12 @@ func (r *LuetSystemRepository) SyncBuildMetadata(path string) error {
return nil return nil
} }
func (r *LuetSystemRepository) Sync(force bool) (*LuetSystemRepository, error) { func (r *LuetSystemRepository) Sync(ctx *types.Context, force bool) (*LuetSystemRepository, error) {
var repoUpdated bool = false var repoUpdated bool = false
var treefs, metafs string var treefs, metafs string
aurora := GetAurora()
Debug("Sync of the repository", r.Name, "in progress...") ctx.Debug("Sync of the repository", r.Name, "in progress...")
c := r.Client() c := r.Client(ctx)
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")
} }
@ -787,10 +785,10 @@ func (r *LuetSystemRepository) Sync(force bool) (*LuetSystemRepository, error) {
// Retrieve remote repository.yaml for retrieve revision and date // 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)
} }
repobasedir := config.LuetCfg.GetSystem().GetRepoDatabaseDirPath(r.GetName()) repobasedir := ctx.Config.GetSystem().GetRepoDatabaseDirPath(r.GetName())
downloadedRepoMeta, err := r.ReadSpecFile(file) downloadedRepoMeta, err := r.ReadSpecFile(file)
if err != nil { if err != nil {
return nil, err return nil, err
@ -821,11 +819,11 @@ func (r *LuetSystemRepository) Sync(force bool) (*LuetSystemRepository, error) {
} }
} else { } else {
treefs, err = config.LuetCfg.GetSystem().TempDir("treefs") treefs, err = ctx.Config.GetSystem().TempDir("treefs")
if err != nil { if err != nil {
return nil, errors.Wrap(err, "Error met while creating tempdir for rootfs") return nil, errors.Wrap(err, "Error met while creating tempdir for rootfs")
} }
metafs, err = config.LuetCfg.GetSystem().TempDir("metafs") metafs, err = ctx.Config.GetSystem().TempDir("metafs")
if err != nil { if err != nil {
return nil, errors.Wrap(err, "Error met whilte creating tempdir for metafs") return nil, errors.Wrap(err, "Error met whilte creating tempdir for metafs")
} }
@ -840,7 +838,7 @@ func (r *LuetSystemRepository) Sync(force bool) (*LuetSystemRepository, error) {
} }
defer os.Remove(treeFileArtifact.Path) defer os.Remove(treeFileArtifact.Path)
Debug("Tree tarball for the repository " + r.GetName() + " downloaded correctly.") ctx.Debug("Tree tarball for the repository " + r.GetName() + " downloaded correctly.")
metaFileArtifact, err := downloadedRepoMeta.getRepoFile(c, REPOFILE_META_KEY) metaFileArtifact, err := downloadedRepoMeta.getRepoFile(c, REPOFILE_META_KEY)
if err != nil { if err != nil {
@ -848,7 +846,7 @@ func (r *LuetSystemRepository) Sync(force bool) (*LuetSystemRepository, error) {
} }
defer os.Remove(metaFileArtifact.Path) defer os.Remove(metaFileArtifact.Path)
Debug("Metadata tarball for the repository " + r.GetName() + " downloaded correctly.") ctx.Debug("Metadata tarball for the repository " + r.GetName() + " downloaded correctly.")
if r.Cached { if r.Cached {
// Copy updated repository.yaml file to repo dir now that the tree is synced. // Copy updated repository.yaml file to repo dir now that the tree is synced.
@ -861,9 +859,9 @@ func (r *LuetSystemRepository) Sync(force bool) (*LuetSystemRepository, error) {
// Remove previous meta dir // Remove previous meta dir
os.RemoveAll(metafs) os.RemoveAll(metafs)
} }
Debug("Decompress tree of the repository " + r.Name + "...") ctx.Debug("Decompress tree of the repository " + r.Name + "...")
err = treeFileArtifact.Unpack(treefs, true) err = treeFileArtifact.Unpack(ctx, treefs, true)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "Error met while unpacking tree") return nil, errors.Wrap(err, "Error met while unpacking tree")
} }
@ -871,22 +869,21 @@ func (r *LuetSystemRepository) Sync(force bool) (*LuetSystemRepository, error) {
// FIXME: It seems that tar with only one file doesn't create destination // FIXME: It seems that tar with only one file doesn't create destination
// directory. I create directory directly for now. // directory. I create directory directly for now.
os.MkdirAll(metafs, os.ModePerm) os.MkdirAll(metafs, os.ModePerm)
err = metaFileArtifact.Unpack(metafs, true) err = metaFileArtifact.Unpack(ctx, metafs, true)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "Error met while unpacking metadata") return nil, errors.Wrap(err, "Error met while unpacking metadata")
} }
tsec, _ := strconv.ParseInt(downloadedRepoMeta.GetLastUpdate(), 10, 64) tsec, _ := strconv.ParseInt(downloadedRepoMeta.GetLastUpdate(), 10, 64)
InfoC( ctx.Info(
aurora.Bold( fmt.Sprintf(":house: Repository %s revision: %d (%s)",
aurora.Red(":house: Repository "+downloadedRepoMeta.GetName()+" revision: ")).String() + downloadedRepoMeta.GetName(),
aurora.Bold(aurora.Green(downloadedRepoMeta.GetRevision())).String() + " - " + downloadedRepoMeta.GetRevision(),
aurora.Bold(aurora.Green(time.Unix(tsec, 0).String())).String(), time.Unix(tsec, 0).String()))
)
} else { } else {
Info("Repository", downloadedRepoMeta.GetName(), "is already up to date.") ctx.Info("Repository", downloadedRepoMeta.GetName(), "is already up to date.")
} }
meta, err := NewLuetSystemRepositoryMetadata( meta, err := NewLuetSystemRepositoryMetadata(
@ -910,16 +907,11 @@ func (r *LuetSystemRepository) Sync(force bool) (*LuetSystemRepository, error) {
// e.g. locally we can override the type (disk), or priority // e.g. locally we can override the type (disk), or priority
// while remotely it could be advertized differently // while remotely it could be advertized differently
r.fill(downloadedRepoMeta) r.fill(downloadedRepoMeta)
ctx.Info(
InfoC( fmt.Sprintf(":information_source: Repository: %s Priority: %d Type: %s",
aurora.Yellow(":information_source:").String() + downloadedRepoMeta.GetName(),
aurora.Magenta("Repository: ").String() + downloadedRepoMeta.GetPriority(),
aurora.Green(aurora.Bold(downloadedRepoMeta.GetName()).String()).String() + downloadedRepoMeta.GetType()))
aurora.Magenta(" Priority: ").String() +
aurora.Bold(aurora.Green(downloadedRepoMeta.GetPriority())).String() +
aurora.Magenta(" Type: ").String() +
aurora.Bold(aurora.Green(downloadedRepoMeta.GetType())).String(),
)
return downloadedRepoMeta, nil return downloadedRepoMeta, nil
} }

View File

@ -24,14 +24,13 @@ import (
"strings" "strings"
"time" "time"
"github.com/mudler/luet/pkg/api/core/types"
artifact "github.com/mudler/luet/pkg/api/core/types/artifact" artifact "github.com/mudler/luet/pkg/api/core/types/artifact"
"github.com/mudler/luet/pkg/bus" "github.com/mudler/luet/pkg/bus"
compiler "github.com/mudler/luet/pkg/compiler" compiler "github.com/mudler/luet/pkg/compiler"
"github.com/mudler/luet/pkg/compiler/backend" "github.com/mudler/luet/pkg/compiler/backend"
"github.com/mudler/luet/pkg/config"
"github.com/mudler/luet/pkg/helpers" "github.com/mudler/luet/pkg/helpers"
"github.com/mudler/luet/pkg/helpers/docker" "github.com/mudler/luet/pkg/helpers/docker"
. "github.com/mudler/luet/pkg/logger"
pkg "github.com/mudler/luet/pkg/package" pkg "github.com/mudler/luet/pkg/package"
"github.com/pkg/errors" "github.com/pkg/errors"
@ -41,18 +40,19 @@ type dockerRepositoryGenerator struct {
b compiler.CompilerBackend b compiler.CompilerBackend
imagePrefix string imagePrefix string
imagePush, force bool imagePush, force bool
context *types.Context
} }
func (l *dockerRepositoryGenerator) Initialize(path string, db pkg.PackageDatabase) ([]*artifact.PackageArtifact, error) { func (l *dockerRepositoryGenerator) Initialize(path string, db pkg.PackageDatabase) ([]*artifact.PackageArtifact, error) {
Info("Generating docker images for packages in", l.imagePrefix) l.context.Info("Generating docker images for packages in", l.imagePrefix)
var art []*artifact.PackageArtifact var art []*artifact.PackageArtifact
var ff = func(currentpath string, info os.FileInfo, err error) error { var ff = func(currentpath string, info os.FileInfo, err error) error {
if err != nil { if err != nil {
Debug("Skipping", info.Name(), err.Error()) l.context.Debug("Skipping", info.Name(), err.Error())
return nil return nil
} }
if info.IsDir() { if info.IsDir() {
Debug("Skipping directories") l.context.Debug("Skipping directories")
return nil return nil
} }
@ -80,7 +80,7 @@ func (l *dockerRepositoryGenerator) Initialize(path string, db pkg.PackageDataba
// We want to include packages that are ONLY referenced in the tree. // We want to include packages that are ONLY referenced in the tree.
// the ones which aren't should be deleted. (TODO: by another cli command?) // the ones which aren't should be deleted. (TODO: by another cli command?)
if _, notfound := db.FindPackage(a.CompileSpec.Package); notfound != nil { if _, notfound := db.FindPackage(a.CompileSpec.Package); notfound != nil {
Debug(fmt.Sprintf("Package %s not found in tree. Ignoring it.", l.context.Debug(fmt.Sprintf("Package %s not found in tree. Ignoring it.",
a.CompileSpec.Package.HumanReadableString())) a.CompileSpec.Package.HumanReadableString()))
return nil return nil
} }
@ -88,16 +88,16 @@ func (l *dockerRepositoryGenerator) Initialize(path string, db pkg.PackageDataba
packageImage := fmt.Sprintf("%s:%s", l.imagePrefix, a.CompileSpec.GetPackage().ImageID()) packageImage := fmt.Sprintf("%s:%s", l.imagePrefix, a.CompileSpec.GetPackage().ImageID())
if l.imagePush && l.b.ImageAvailable(packageImage) && !l.force { if l.imagePush && l.b.ImageAvailable(packageImage) && !l.force {
Info("Image", packageImage, "already present, skipping. use --force-push to override") l.context.Info("Image", packageImage, "already present, skipping. use --force-push to override")
} else { } else {
Info("Generating final image", packageImage, l.context.Info("Generating final image", packageImage,
"for package ", a.CompileSpec.GetPackage().HumanReadableString()) "for package ", a.CompileSpec.GetPackage().HumanReadableString())
if opts, err := a.GenerateFinalImage(packageImage, l.b, true); err != nil { if opts, err := a.GenerateFinalImage(l.context, packageImage, l.b, true); err != nil {
return errors.Wrap(err, "Failed generating metadata tree"+opts.ImageName) return errors.Wrap(err, "Failed generating metadata tree"+opts.ImageName)
} }
} }
if l.imagePush { if l.imagePush {
if err := pushImage(l.b, packageImage, l.force); err != nil { if err := pushImage(l.context, l.b, packageImage, l.force); err != nil {
return errors.Wrapf(err, "Failed while pushing image: '%s'", packageImage) return errors.Wrapf(err, "Failed while pushing image: '%s'", packageImage)
} }
} }
@ -115,21 +115,21 @@ func (l *dockerRepositoryGenerator) Initialize(path string, db pkg.PackageDataba
return art, nil return art, nil
} }
func pushImage(b compiler.CompilerBackend, image string, force bool) error { func pushImage(ctx *types.Context, b compiler.CompilerBackend, image string, force bool) error {
if b.ImageAvailable(image) && !force { if b.ImageAvailable(image) && !force {
Debug("Image", image, "already present, skipping") ctx.Debug("Image", image, "already present, skipping")
return nil return nil
} }
return b.Push(backend.Options{ImageName: image}) return b.Push(backend.Options{ImageName: image})
} }
func (d *dockerRepositoryGenerator) pushFileFromArtifact(a *artifact.PackageArtifact, imageTree string) error { func (d *dockerRepositoryGenerator) pushFileFromArtifact(a *artifact.PackageArtifact, imageTree string) error {
Debug("Generating image", imageTree) d.context.Debug("Generating image", imageTree)
if opts, err := a.GenerateFinalImage(imageTree, d.b, false); err != nil { if opts, err := a.GenerateFinalImage(d.context, imageTree, d.b, false); err != nil {
return errors.Wrap(err, "Failed generating metadata tree "+opts.ImageName) return errors.Wrap(err, "Failed generating metadata tree "+opts.ImageName)
} }
if d.imagePush { if d.imagePush {
if err := pushImage(d.b, imageTree, true); err != nil { if err := pushImage(d.context, d.b, imageTree, true); err != nil {
return errors.Wrapf(err, "Failed while pushing image: '%s'", imageTree) return errors.Wrapf(err, "Failed while pushing image: '%s'", imageTree)
} }
} }
@ -138,7 +138,7 @@ func (d *dockerRepositoryGenerator) pushFileFromArtifact(a *artifact.PackageArti
func (d *dockerRepositoryGenerator) pushRepoMetadata(repospec string, r *LuetSystemRepository) error { func (d *dockerRepositoryGenerator) pushRepoMetadata(repospec string, r *LuetSystemRepository) error {
// create temp dir for metafile // create temp dir for metafile
metaDir, err := config.LuetCfg.GetSystem().TempDir("metadata") metaDir, err := d.context.Config.GetSystem().TempDir("metadata")
if err != nil { if err != nil {
return errors.Wrap(err, "Error met while creating tempdir for metadata") return errors.Wrap(err, "Error met while creating tempdir for metadata")
} }
@ -161,13 +161,13 @@ func (d *dockerRepositoryGenerator) pushRepoMetadata(repospec string, r *LuetSys
func (d *dockerRepositoryGenerator) pushImageFromArtifact(a *artifact.PackageArtifact, b compiler.CompilerBackend, checkIfExists bool) error { func (d *dockerRepositoryGenerator) pushImageFromArtifact(a *artifact.PackageArtifact, b compiler.CompilerBackend, checkIfExists bool) error {
// we generate a new archive containing the required compressed file. // we generate a new archive containing the required compressed file.
// TODO: Bundle all the extra files in 1 docker image only, instead of an image for each file // TODO: Bundle all the extra files in 1 docker image only, instead of an image for each file
treeArchive, err := artifact.CreateArtifactForFile(a.Path) treeArchive, err := artifact.CreateArtifactForFile(d.context, a.Path)
if err != nil { if err != nil {
return errors.Wrap(err, "failed generating checksums for tree") return errors.Wrap(err, "failed generating checksums for tree")
} }
imageTree := fmt.Sprintf("%s:%s", d.imagePrefix, docker.StripInvalidStringsFromImage(a.GetFileName())) imageTree := fmt.Sprintf("%s:%s", d.imagePrefix, docker.StripInvalidStringsFromImage(a.GetFileName()))
if checkIfExists && d.imagePush && d.b.ImageAvailable(imageTree) && !d.force { if checkIfExists && d.imagePush && d.b.ImageAvailable(imageTree) && !d.force {
Info("Image", imageTree, "already present, skipping. use --force-push to override") d.context.Info("Image", imageTree, "already present, skipping. use --force-push to override")
return nil return nil
} else { } else {
return d.pushFileFromArtifact(treeArchive, imageTree) return d.pushFileFromArtifact(treeArchive, imageTree)
@ -184,7 +184,7 @@ func (d *dockerRepositoryGenerator) Generate(r *LuetSystemRepository, imagePrefi
r.LastUpdate = strconv.FormatInt(time.Now().Unix(), 10) r.LastUpdate = strconv.FormatInt(time.Now().Unix(), 10)
repoTemp, err := config.LuetCfg.GetSystem().TempDir("repo") repoTemp, err := d.context.Config.GetSystem().TempDir("repo")
if err != nil { if err != nil {
return errors.Wrap(err, "error met while creating tempdir for repository") return errors.Wrap(err, "error met while creating tempdir for repository")
} }
@ -207,7 +207,7 @@ func (d *dockerRepositoryGenerator) Generate(r *LuetSystemRepository, imagePrefi
return err return err
} }
Info(fmt.Sprintf( d.context.Info(fmt.Sprintf(
"For repository %s creating revision %d and last update %s...", "For repository %s creating revision %d and last update %s...",
r.Name, r.Revision, r.LastUpdate, r.Name, r.Revision, r.LastUpdate,
)) ))
@ -221,7 +221,7 @@ func (d *dockerRepositoryGenerator) Generate(r *LuetSystemRepository, imagePrefi
}) })
// Create tree and repository file // Create tree and repository file
a, err := r.AddTree(r.GetTree(), repoTemp, REPOFILE_TREE_KEY, NewDefaultTreeRepositoryFile()) a, err := r.AddTree(d.context, r.GetTree(), repoTemp, REPOFILE_TREE_KEY, NewDefaultTreeRepositoryFile())
if err != nil { if err != nil {
return errors.Wrap(err, "error met while adding runtime tree to repository") return errors.Wrap(err, "error met while adding runtime tree to repository")
} }
@ -232,7 +232,7 @@ func (d *dockerRepositoryGenerator) Generate(r *LuetSystemRepository, imagePrefi
return errors.Wrap(err, "error met while pushing runtime tree") return errors.Wrap(err, "error met while pushing runtime tree")
} }
a, err = r.AddTree(r.BuildTree, repoTemp, REPOFILE_COMPILER_TREE_KEY, NewDefaultCompilerTreeRepositoryFile()) a, err = r.AddTree(d.context, r.BuildTree, repoTemp, REPOFILE_COMPILER_TREE_KEY, NewDefaultCompilerTreeRepositoryFile())
if err != nil { if err != nil {
return errors.Wrap(err, "error met while adding compiler tree to repository") return errors.Wrap(err, "error met while adding compiler tree to repository")
} }
@ -243,13 +243,13 @@ func (d *dockerRepositoryGenerator) Generate(r *LuetSystemRepository, imagePrefi
} }
// create temp dir for metafile // create temp dir for metafile
metaDir, err := config.LuetCfg.GetSystem().TempDir("metadata") metaDir, err := d.context.Config.GetSystem().TempDir("metadata")
if err != nil { if err != nil {
return errors.Wrap(err, "error met while creating tempdir for metadata") return errors.Wrap(err, "error met while creating tempdir for metadata")
} }
defer os.RemoveAll(metaDir) // clean up defer os.RemoveAll(metaDir) // clean up
a, err = r.AddMetadata(repospec, metaDir) a, err = r.AddMetadata(d.context, repospec, metaDir)
if err != nil { if err != nil {
return errors.Wrap(err, "failed adding Metadata file to repository") return errors.Wrap(err, "failed adding Metadata file to repository")
} }

View File

@ -24,26 +24,26 @@ import (
"strings" "strings"
"time" "time"
"github.com/mudler/luet/pkg/api/core/types"
artifact "github.com/mudler/luet/pkg/api/core/types/artifact" artifact "github.com/mudler/luet/pkg/api/core/types/artifact"
. "github.com/mudler/luet/pkg/logger"
pkg "github.com/mudler/luet/pkg/package" pkg "github.com/mudler/luet/pkg/package"
"github.com/mudler/luet/pkg/bus" "github.com/mudler/luet/pkg/bus"
"github.com/pkg/errors" "github.com/pkg/errors"
) )
type localRepositoryGenerator struct{} type localRepositoryGenerator struct{ context *types.Context }
func (l *localRepositoryGenerator) Initialize(path string, db pkg.PackageDatabase) ([]*artifact.PackageArtifact, error) { func (l *localRepositoryGenerator) Initialize(path string, db pkg.PackageDatabase) ([]*artifact.PackageArtifact, error) {
return buildPackageIndex(path, db) return buildPackageIndex(l.context, path, db)
} }
func buildPackageIndex(path string, db pkg.PackageDatabase) ([]*artifact.PackageArtifact, error) { func buildPackageIndex(ctx *types.Context, path string, db pkg.PackageDatabase) ([]*artifact.PackageArtifact, error) {
var art []*artifact.PackageArtifact var art []*artifact.PackageArtifact
var ff = func(currentpath string, info os.FileInfo, err error) error { var ff = func(currentpath string, info os.FileInfo, err error) error {
if err != nil { if err != nil {
Debug("Failed walking", err.Error()) ctx.Debug("Failed walking", err.Error())
return err return err
} }
@ -64,7 +64,7 @@ func buildPackageIndex(path string, db pkg.PackageDatabase) ([]*artifact.Package
// We want to include packages that are ONLY referenced in the tree. // We want to include packages that are ONLY referenced in the tree.
// the ones which aren't should be deleted. (TODO: by another cli command?) // the ones which aren't should be deleted. (TODO: by another cli command?)
if _, notfound := db.FindPackage(a.CompileSpec.GetPackage()); notfound != nil { if _, notfound := db.FindPackage(a.CompileSpec.GetPackage()); notfound != nil {
Debug(fmt.Sprintf("Package %s not found in tree. Ignoring it.", ctx.Debug(fmt.Sprintf("Package %s not found in tree. Ignoring it.",
a.CompileSpec.GetPackage().HumanReadableString())) a.CompileSpec.GetPackage().HumanReadableString()))
return nil return nil
} }
@ -83,7 +83,7 @@ func buildPackageIndex(path string, db pkg.PackageDatabase) ([]*artifact.Package
} }
// Generate creates a Local luet repository // Generate creates a Local luet repository
func (*localRepositoryGenerator) Generate(r *LuetSystemRepository, dst string, resetRevision bool) error { func (g *localRepositoryGenerator) Generate(r *LuetSystemRepository, dst string, resetRevision bool) error {
err := os.MkdirAll(dst, os.ModePerm) err := os.MkdirAll(dst, os.ModePerm)
if err != nil { if err != nil {
return err return err
@ -96,7 +96,7 @@ func (*localRepositoryGenerator) Generate(r *LuetSystemRepository, dst string, r
return err return err
} }
Info(fmt.Sprintf( g.context.Info(fmt.Sprintf(
"Repository %s: creating revision %d and last update %s...", "Repository %s: creating revision %d and last update %s...",
r.Name, r.Revision, r.LastUpdate, r.Name, r.Revision, r.LastUpdate,
)) ))
@ -109,15 +109,15 @@ func (*localRepositoryGenerator) Generate(r *LuetSystemRepository, dst string, r
Path: dst, Path: dst,
}) })
if _, err := r.AddTree(r.GetTree(), dst, REPOFILE_TREE_KEY, NewDefaultTreeRepositoryFile()); err != nil { if _, err := r.AddTree(g.context, r.GetTree(), dst, REPOFILE_TREE_KEY, NewDefaultTreeRepositoryFile()); err != nil {
return errors.Wrap(err, "error met while adding runtime tree to repository") return errors.Wrap(err, "error met while adding runtime tree to repository")
} }
if _, err := r.AddTree(r.BuildTree, dst, REPOFILE_COMPILER_TREE_KEY, NewDefaultCompilerTreeRepositoryFile()); err != nil { if _, err := r.AddTree(g.context, r.BuildTree, dst, REPOFILE_COMPILER_TREE_KEY, NewDefaultCompilerTreeRepositoryFile()); err != nil {
return errors.Wrap(err, "error met while adding compiler tree to repository") return errors.Wrap(err, "error met while adding compiler tree to repository")
} }
if _, err := r.AddMetadata(repospec, dst); err != nil { if _, err := r.AddMetadata(g.context, repospec, dst); err != nil {
return errors.Wrap(err, "failed adding Metadata file to repository") return errors.Wrap(err, "failed adding Metadata file to repository")
} }

View File

@ -16,8 +16,8 @@
package installer package installer
import ( import (
"github.com/mudler/luet/pkg/api/core/types"
"github.com/mudler/luet/pkg/compiler" "github.com/mudler/luet/pkg/compiler"
"github.com/mudler/luet/pkg/config"
pkg "github.com/mudler/luet/pkg/package" pkg "github.com/mudler/luet/pkg/package"
) )
@ -33,7 +33,7 @@ type RepositoryConfig struct {
CompilerBackend compiler.CompilerBackend CompilerBackend compiler.CompilerBackend
ImagePrefix string ImagePrefix string
config *config.LuetConfig context *types.Context
PushImages, Force, FromRepository, FromMetadata bool PushImages, Force, FromRepository, FromMetadata bool
} }
@ -51,9 +51,9 @@ func (cfg *RepositoryConfig) Apply(opts ...RepositoryOption) error {
return nil return nil
} }
func WithConfig(c *config.LuetConfig) func(cfg *RepositoryConfig) error { func WithContext(c *types.Context) func(cfg *RepositoryConfig) error {
return func(cfg *RepositoryConfig) error { return func(cfg *RepositoryConfig) error {
cfg.config = c cfg.context = c
return nil return nil
} }
} }

View File

@ -28,6 +28,7 @@ import (
artifact "github.com/mudler/luet/pkg/api/core/types/artifact" artifact "github.com/mudler/luet/pkg/api/core/types/artifact"
"github.com/mudler/luet/pkg/compiler" "github.com/mudler/luet/pkg/compiler"
backend "github.com/mudler/luet/pkg/compiler/backend" backend "github.com/mudler/luet/pkg/compiler/backend"
"github.com/mudler/luet/pkg/compiler/types/options"
compilerspec "github.com/mudler/luet/pkg/compiler/types/spec" compilerspec "github.com/mudler/luet/pkg/compiler/types/spec"
"github.com/mudler/luet/pkg/helpers" "github.com/mudler/luet/pkg/helpers"
fileHelper "github.com/mudler/luet/pkg/helpers/file" fileHelper "github.com/mudler/luet/pkg/helpers/file"
@ -49,14 +50,16 @@ func dockerStubRepo(tmpdir, tree, image string, push, force bool) (*LuetSystemRe
WithSource(tmpdir), WithSource(tmpdir),
WithTree(tree), WithTree(tree),
WithDatabase(pkg.NewInMemoryDatabase(false)), WithDatabase(pkg.NewInMemoryDatabase(false)),
WithCompilerBackend(backend.NewSimpleDockerBackend()), WithCompilerBackend(backend.NewSimpleDockerBackend(types.NewContext())),
WithImagePrefix(image), WithImagePrefix(image),
WithPushImages(push), WithPushImages(push),
WithContext(types.NewContext()),
WithForce(force)) WithForce(force))
} }
var _ = Describe("Repository", func() { var _ = Describe("Repository", func() {
Context("Generation", func() { Context("Generation", func() {
ctx := types.NewContext()
It("Generate repository metadata", func() { It("Generate repository metadata", func() {
tmpdir, err := ioutil.TempDir("", "tree") tmpdir, err := ioutil.TempDir("", "tree")
@ -70,7 +73,7 @@ var _ = Describe("Repository", func() {
Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(3)) Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(3))
compiler := compiler.NewLuetCompiler(backend.NewSimpleDockerBackend(), generalRecipe.GetDatabase()) compiler := compiler.NewLuetCompiler(backend.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase())
spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}) spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"})
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
@ -110,7 +113,7 @@ var _ = Describe("Repository", func() {
Expect(fileHelper.Exists(spec.Rel(REPOSITORY_SPECFILE))).ToNot(BeTrue()) Expect(fileHelper.Exists(spec.Rel(REPOSITORY_SPECFILE))).ToNot(BeTrue())
Expect(fileHelper.Exists(spec.Rel(TREE_TARBALL + ".gz"))).ToNot(BeTrue()) Expect(fileHelper.Exists(spec.Rel(TREE_TARBALL + ".gz"))).ToNot(BeTrue())
Expect(fileHelper.Exists(spec.Rel(REPOSITORY_METAFILE + ".tar"))).ToNot(BeTrue()) Expect(fileHelper.Exists(spec.Rel(REPOSITORY_METAFILE + ".tar"))).ToNot(BeTrue())
err = repo.Write(tmpdir, false, true) err = repo.Write(ctx, tmpdir, false, true)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
Expect(fileHelper.Exists(spec.Rel(REPOSITORY_SPECFILE))).To(BeTrue()) Expect(fileHelper.Exists(spec.Rel(REPOSITORY_SPECFILE))).To(BeTrue())
@ -137,11 +140,11 @@ var _ = Describe("Repository", func() {
Expect(len(generalRecipe2.GetDatabase().GetPackages())).To(Equal(1)) Expect(len(generalRecipe2.GetDatabase().GetPackages())).To(Equal(1))
Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(3)) Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(3))
compiler2 := compiler.NewLuetCompiler(backend.NewSimpleDockerBackend(), generalRecipe2.GetDatabase()) compiler2 := compiler.NewLuetCompiler(backend.NewSimpleDockerBackend(ctx), generalRecipe2.GetDatabase(), options.WithContext(types.NewContext()))
spec2, err := compiler2.FromPackage(&pkg.DefaultPackage{Name: "alpine", Category: "seed", Version: "1.0"}) spec2, err := compiler2.FromPackage(&pkg.DefaultPackage{Name: "alpine", Category: "seed", Version: "1.0"})
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
compiler := compiler.NewLuetCompiler(backend.NewSimpleDockerBackend(), generalRecipe.GetDatabase()) compiler := compiler.NewLuetCompiler(backend.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase(), options.WithContext(types.NewContext()))
spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}) spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"})
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
@ -190,7 +193,7 @@ var _ = Describe("Repository", func() {
Expect(fileHelper.Exists(spec.Rel(REPOSITORY_SPECFILE))).ToNot(BeTrue()) Expect(fileHelper.Exists(spec.Rel(REPOSITORY_SPECFILE))).ToNot(BeTrue())
Expect(fileHelper.Exists(spec.Rel(TREE_TARBALL + ".gz"))).ToNot(BeTrue()) Expect(fileHelper.Exists(spec.Rel(TREE_TARBALL + ".gz"))).ToNot(BeTrue())
Expect(fileHelper.Exists(spec.Rel(REPOSITORY_METAFILE + ".tar"))).ToNot(BeTrue()) Expect(fileHelper.Exists(spec.Rel(REPOSITORY_METAFILE + ".tar"))).ToNot(BeTrue())
err = repo.Write(tmpdir, false, true) err = repo.Write(ctx, tmpdir, false, true)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
Expect(fileHelper.Exists(spec.Rel(REPOSITORY_SPECFILE))).To(BeTrue()) Expect(fileHelper.Exists(spec.Rel(REPOSITORY_SPECFILE))).To(BeTrue())
@ -206,7 +209,7 @@ urls:
- "`+tmpdir+`" - "`+tmpdir+`"
`), pkg.NewInMemoryDatabase(false)) `), pkg.NewInMemoryDatabase(false))
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
repos, err := repository.Sync(true) repos, err := repository.Sync(ctx, true)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
_, err = repos.GetTree().GetDatabase().FindPackage(spec.GetPackage()) _, err = repos.GetTree().GetDatabase().FindPackage(spec.GetPackage())
@ -234,11 +237,11 @@ urls:
Expect(len(generalRecipe2.GetDatabase().GetPackages())).To(Equal(1)) Expect(len(generalRecipe2.GetDatabase().GetPackages())).To(Equal(1))
Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(3)) Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(3))
compiler2 := compiler.NewLuetCompiler(backend.NewSimpleDockerBackend(), generalRecipe2.GetDatabase()) compiler2 := compiler.NewLuetCompiler(backend.NewSimpleDockerBackend(ctx), generalRecipe2.GetDatabase(), options.WithContext(ctx))
spec2, err := compiler2.FromPackage(&pkg.DefaultPackage{Name: "alpine", Category: "seed", Version: "1.0"}) spec2, err := compiler2.FromPackage(&pkg.DefaultPackage{Name: "alpine", Category: "seed", Version: "1.0"})
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
compiler := compiler.NewLuetCompiler(backend.NewSimpleDockerBackend(), generalRecipe.GetDatabase()) compiler := compiler.NewLuetCompiler(backend.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase(), options.WithContext(ctx))
spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}) spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"})
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
@ -291,6 +294,7 @@ urls:
WithSource(tmpdir), WithSource(tmpdir),
FromMetadata(true), // Enabling from metadata makes the package visible FromMetadata(true), // Enabling from metadata makes the package visible
WithTree("../../tests/fixtures/buildable"), WithTree("../../tests/fixtures/buildable"),
WithContext(ctx),
WithDatabase(pkg.NewInMemoryDatabase(false)), WithDatabase(pkg.NewInMemoryDatabase(false)),
) )
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
@ -298,7 +302,7 @@ urls:
Expect(fileHelper.Exists(spec.Rel(REPOSITORY_SPECFILE))).ToNot(BeTrue()) Expect(fileHelper.Exists(spec.Rel(REPOSITORY_SPECFILE))).ToNot(BeTrue())
Expect(fileHelper.Exists(spec.Rel(TREE_TARBALL + ".gz"))).ToNot(BeTrue()) Expect(fileHelper.Exists(spec.Rel(TREE_TARBALL + ".gz"))).ToNot(BeTrue())
Expect(fileHelper.Exists(spec.Rel(REPOSITORY_METAFILE + ".tar"))).ToNot(BeTrue()) Expect(fileHelper.Exists(spec.Rel(REPOSITORY_METAFILE + ".tar"))).ToNot(BeTrue())
err = repo.Write(tmpdir, false, true) err = repo.Write(ctx, tmpdir, false, true)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
Expect(fileHelper.Exists(spec.Rel(REPOSITORY_SPECFILE))).To(BeTrue()) Expect(fileHelper.Exists(spec.Rel(REPOSITORY_SPECFILE))).To(BeTrue())
@ -314,7 +318,7 @@ urls:
- "`+tmpdir+`" - "`+tmpdir+`"
`), pkg.NewInMemoryDatabase(false)) `), pkg.NewInMemoryDatabase(false))
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
repos, err := repository.Sync(true) repos, err := repository.Sync(ctx, true)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
_, err = repos.GetTree().GetDatabase().FindPackage(spec.GetPackage()) _, err = repos.GetTree().GetDatabase().FindPackage(spec.GetPackage())
@ -345,15 +349,16 @@ urls:
}) })
Context("Docker repository", func() { Context("Docker repository", func() {
repoImage := os.Getenv("UNIT_TEST_DOCKER_IMAGE_REPOSITORY") repoImage := os.Getenv("UNIT_TEST_DOCKER_IMAGE_REPOSITORY")
ctx := types.NewContext()
BeforeEach(func() { BeforeEach(func() {
if repoImage == "" { if repoImage == "" {
Skip("UNIT_TEST_DOCKER_IMAGE_REPOSITORY not specified") Skip("UNIT_TEST_DOCKER_IMAGE_REPOSITORY not specified")
} }
ctx = types.NewContext()
}) })
It("generates images", func() { It("generates images", func() {
b := backend.NewSimpleDockerBackend() b := backend.NewSimpleDockerBackend(ctx)
tmpdir, err := ioutil.TempDir("", "tree") tmpdir, err := ioutil.TempDir("", "tree")
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
defer os.RemoveAll(tmpdir) // clean up defer os.RemoveAll(tmpdir) // clean up
@ -365,7 +370,8 @@ urls:
Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(3)) Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(3))
localcompiler := compiler.NewLuetCompiler(backend.NewSimpleDockerBackend(), generalRecipe.GetDatabase()) localcompiler := compiler.NewLuetCompiler(
backend.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase(), options.WithContext(ctx))
spec, err := localcompiler.FromPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}) spec, err := localcompiler.FromPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"})
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
@ -392,7 +398,7 @@ urls:
Expect(fileHelper.Exists(spec.Rel(REPOSITORY_SPECFILE))).ToNot(BeTrue()) Expect(fileHelper.Exists(spec.Rel(REPOSITORY_SPECFILE))).ToNot(BeTrue())
Expect(fileHelper.Exists(spec.Rel(TREE_TARBALL + ".gz"))).ToNot(BeTrue()) Expect(fileHelper.Exists(spec.Rel(TREE_TARBALL + ".gz"))).ToNot(BeTrue())
Expect(fileHelper.Exists(spec.Rel(REPOSITORY_METAFILE + ".tar"))).ToNot(BeTrue()) Expect(fileHelper.Exists(spec.Rel(REPOSITORY_METAFILE + ".tar"))).ToNot(BeTrue())
err = repo.Write(repoImage, false, true) err = repo.Write(ctx, repoImage, false, true)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
Expect(b.ImageAvailable(fmt.Sprintf("%s:%s", repoImage, "tree.tar.gz"))).To(BeTrue()) Expect(b.ImageAvailable(fmt.Sprintf("%s:%s", repoImage, "tree.tar.gz"))).To(BeTrue())
@ -404,7 +410,7 @@ urls:
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
defer os.RemoveAll(extracted) // clean up defer os.RemoveAll(extracted) // clean up
c := repo.Client() c := repo.Client(ctx)
f, err := c.DownloadFile("repository.yaml") f, err := c.DownloadFile("repository.yaml")
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
@ -422,12 +428,12 @@ urls:
}) })
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
Expect(a.Unpack(extracted, false)).ToNot(HaveOccurred()) Expect(a.Unpack(ctx, extracted, false)).ToNot(HaveOccurred())
Expect(fileHelper.Read(filepath.Join(extracted, "test6"))).To(Equal("artifact6\n")) Expect(fileHelper.Read(filepath.Join(extracted, "test6"))).To(Equal("artifact6\n"))
}) })
It("generates images of virtual packages", func() { It("generates images of virtual packages", func() {
b := backend.NewSimpleDockerBackend() b := backend.NewSimpleDockerBackend(ctx)
tmpdir, err := ioutil.TempDir("", "tree") tmpdir, err := ioutil.TempDir("", "tree")
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
defer os.RemoveAll(tmpdir) // clean up defer os.RemoveAll(tmpdir) // clean up
@ -439,7 +445,8 @@ urls:
Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(5)) Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(5))
localcompiler := compiler.NewLuetCompiler(backend.NewSimpleDockerBackend(), generalRecipe.GetDatabase()) localcompiler := compiler.NewLuetCompiler(
backend.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase(), options.WithContext(ctx))
spec, err := localcompiler.FromPackage(&pkg.DefaultPackage{Name: "a", Category: "test", Version: "1.99"}) spec, err := localcompiler.FromPackage(&pkg.DefaultPackage{Name: "a", Category: "test", Version: "1.99"})
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
@ -463,7 +470,7 @@ urls:
Expect(fileHelper.Exists(spec.Rel(REPOSITORY_SPECFILE))).ToNot(BeTrue()) Expect(fileHelper.Exists(spec.Rel(REPOSITORY_SPECFILE))).ToNot(BeTrue())
Expect(fileHelper.Exists(spec.Rel(TREE_TARBALL + ".gz"))).ToNot(BeTrue()) Expect(fileHelper.Exists(spec.Rel(TREE_TARBALL + ".gz"))).ToNot(BeTrue())
Expect(fileHelper.Exists(spec.Rel(REPOSITORY_METAFILE + ".tar"))).ToNot(BeTrue()) Expect(fileHelper.Exists(spec.Rel(REPOSITORY_METAFILE + ".tar"))).ToNot(BeTrue())
err = repo.Write(repoImage, false, true) err = repo.Write(ctx, repoImage, false, true)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
Expect(b.ImageAvailable(fmt.Sprintf("%s:%s", repoImage, "tree.tar.gz"))).To(BeTrue()) Expect(b.ImageAvailable(fmt.Sprintf("%s:%s", repoImage, "tree.tar.gz"))).To(BeTrue())
@ -475,7 +482,7 @@ urls:
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
defer os.RemoveAll(extracted) // clean up defer os.RemoveAll(extracted) // clean up
c := repo.Client() c := repo.Client(ctx)
f, err := c.DownloadFile("repository.yaml") f, err := c.DownloadFile("repository.yaml")
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
@ -493,7 +500,7 @@ urls:
}) })
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
Expect(a.Unpack(extracted, false)).ToNot(HaveOccurred()) Expect(a.Unpack(ctx, extracted, false)).ToNot(HaveOccurred())
Expect(fileHelper.DirectoryIsEmpty(extracted)).To(BeFalse()) Expect(fileHelper.DirectoryIsEmpty(extracted)).To(BeFalse())
content, err := ioutil.ReadFile(filepath.Join(extracted, ".virtual")) content, err := ioutil.ReadFile(filepath.Join(extracted, ".virtual"))

View File

@ -4,9 +4,9 @@ import (
"sync" "sync"
"github.com/hashicorp/go-multierror" "github.com/hashicorp/go-multierror"
"github.com/mudler/luet/pkg/api/core/types"
"github.com/mudler/luet/pkg/helpers" "github.com/mudler/luet/pkg/helpers"
fileHelper "github.com/mudler/luet/pkg/helpers/file" fileHelper "github.com/mudler/luet/pkg/helpers/file"
. "github.com/mudler/luet/pkg/logger"
pkg "github.com/mudler/luet/pkg/package" pkg "github.com/mudler/luet/pkg/package"
"github.com/mudler/luet/pkg/tree" "github.com/mudler/luet/pkg/tree"
) )
@ -22,32 +22,30 @@ func (s *System) World() (pkg.Packages, error) {
return s.Database.World(), nil return s.Database.World(), nil
} }
type templatedata map[string]interface{} func (s *System) ExecuteFinalizers(ctx *types.Context, packs []pkg.Package) error {
func (s *System) ExecuteFinalizers(packs []pkg.Package) error {
var errs error var errs error
executedFinalizer := map[string]bool{} executedFinalizer := map[string]bool{}
for _, p := range packs { for _, p := range packs {
if fileHelper.Exists(p.Rel(tree.FinalizerFile)) { if fileHelper.Exists(p.Rel(tree.FinalizerFile)) {
out, err := helpers.RenderFiles(helpers.ChartFile(p.Rel(tree.FinalizerFile)), p.Rel(pkg.PackageDefinitionFile)) out, err := helpers.RenderFiles(helpers.ChartFile(p.Rel(tree.FinalizerFile)), p.Rel(pkg.PackageDefinitionFile))
if err != nil { if err != nil {
Warning("Failed rendering finalizer for ", p.HumanReadableString(), err.Error()) ctx.Warning("Failed rendering finalizer for ", p.HumanReadableString(), err.Error())
errs = multierror.Append(errs, err) errs = multierror.Append(errs, err)
continue continue
} }
if _, exists := executedFinalizer[p.GetFingerPrint()]; !exists { if _, exists := executedFinalizer[p.GetFingerPrint()]; !exists {
executedFinalizer[p.GetFingerPrint()] = true executedFinalizer[p.GetFingerPrint()] = true
Info("Executing finalizer for " + p.HumanReadableString()) ctx.Info("Executing finalizer for " + p.HumanReadableString())
finalizer, err := NewLuetFinalizerFromYaml([]byte(out)) finalizer, err := NewLuetFinalizerFromYaml([]byte(out))
if err != nil { if err != nil {
Warning("Failed reading finalizer for ", p.HumanReadableString(), err.Error()) ctx.Warning("Failed reading finalizer for ", p.HumanReadableString(), err.Error())
errs = multierror.Append(errs, err) errs = multierror.Append(errs, err)
continue continue
} }
err = finalizer.RunInstall(s) err = finalizer.RunInstall(ctx, s)
if err != nil { if err != nil {
Warning("Failed running finalizer for ", p.HumanReadableString(), err.Error()) ctx.Warning("Failed running finalizer for ", p.HumanReadableString(), err.Error())
errs = multierror.Append(errs, err) errs = multierror.Append(errs, err)
continue continue
} }
@ -79,15 +77,11 @@ func (s *System) Clean() {
} }
func (s *System) ExistsPackageFile(file string) (bool, pkg.Package, error) { func (s *System) ExistsPackageFile(file string) (bool, pkg.Package, error) {
Debug("Checking if file ", file, "belongs to any package")
s.buildFileIndex() s.buildFileIndex()
s.Lock() s.Lock()
defer s.Unlock() defer s.Unlock()
if p, exists := s.fileIndex[file]; exists { if p, exists := s.fileIndex[file]; exists {
Debug(file, "belongs already to", p.HumanReadableString())
return exists, p, nil return exists, p, nil
} }
Debug(file, "doesn't belong to any package")
return false, nil, nil return false, nil, nil
} }

View File

@ -1,329 +0,0 @@
package logger
import (
"fmt"
"os"
"path"
"regexp"
"runtime"
"strings"
"sync"
. "github.com/mudler/luet/pkg/config"
"github.com/kyokomi/emoji"
. "github.com/logrusorgru/aurora"
"github.com/pterm/pterm"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
)
var s *pterm.SpinnerPrinter
var z *zap.Logger = nil
var aurora Aurora = nil
var spinnerLock = sync.Mutex{}
func NewSpinner() {
if s == nil {
s = pterm.DefaultSpinner.WithShowTimer(false).WithRemoveWhenDone(true)
}
}
func InitAurora() {
if aurora == nil {
aurora = NewAurora(LuetCfg.GetLogging().Color)
}
}
func GetAurora() Aurora {
return aurora
}
func NoColor() {
pterm.DisableColor()
}
func Ask() bool {
var input string
Info("Do you want to continue with this operation? [y/N]: ")
_, err := fmt.Scanln(&input)
if err != nil {
return false
}
input = strings.ToLower(input)
if input == "y" || input == "yes" {
return true
}
return false
}
func ZapLogger() error {
var err error
if z == nil {
// TODO: test permission for open logfile.
cfg := zap.NewProductionConfig()
cfg.OutputPaths = []string{LuetCfg.GetLogging().Path}
cfg.Level = level2AtomicLevel(LuetCfg.GetLogging().Level)
cfg.ErrorOutputPaths = []string{}
if LuetCfg.GetLogging().JsonFormat {
cfg.Encoding = "json"
} else {
cfg.Encoding = "console"
}
cfg.DisableCaller = true
cfg.DisableStacktrace = true
cfg.EncoderConfig.TimeKey = "time"
cfg.EncoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder
z, err = cfg.Build()
if err != nil {
fmt.Fprint(os.Stderr, "Error on initialize file logger: "+err.Error()+"\n")
return err
}
}
return nil
}
func Spinner(i int) {
spinnerLock.Lock()
defer spinnerLock.Unlock()
var confLevel int
if LuetCfg.GetGeneral().Debug {
confLevel = 3
} else {
confLevel = level2Number(LuetCfg.GetLogging().Level)
}
if 2 > confLevel {
return
}
if i > 43 {
i = 43
}
if s != nil && !s.IsActive {
// s.UpdateCharSet(spinner.CharSets[i])
//s.Start() // Start the spinner
// time.Sleep(second)
// for i := 14; i > 0; i-- {
// if i > 1 {
// introSpinner.UpdateText("Waiting for " + strconv.Itoa(i) + " seconds...")
// } else {
// introSpinner.UpdateText("Waiting for " + strconv.Itoa(i) + " second...")
// }
// time.Sleep(second)
// }
// s = introSpinner
s, _ = s.Start()
//introSpinner.Stop()
}
}
func Screen(text string) {
pterm.DefaultHeader.WithBackgroundStyle(pterm.NewStyle(pterm.BgLightBlue)).WithMargin(2).Println(text)
//pterm.DefaultCenter.Print(pterm.DefaultHeader.WithFullWidth().WithBackgroundStyle(pterm.NewStyle(pterm.BgLightBlue)).WithMargin(10).Sprint(text))
}
func SpinnerText(suffix, prefix string) {
if s != nil {
spinnerLock.Lock()
defer spinnerLock.Unlock()
if LuetCfg.GetGeneral().Debug {
fmt.Println(fmt.Sprintf("%s %s",
Bold(Cyan(prefix)).String(),
Bold(Magenta(suffix)).BgBlack().String(),
))
} else {
s.UpdateText(suffix + prefix)
}
}
}
func SpinnerStop() {
spinnerLock.Lock()
defer spinnerLock.Unlock()
var confLevel int
if LuetCfg.GetGeneral().Debug {
confLevel = 3
} else {
confLevel = level2Number(LuetCfg.GetLogging().Level)
}
if 2 > confLevel {
return
}
if s != nil {
s.Success()
}
}
func level2Number(level string) int {
switch level {
case "error":
return 0
case "warning":
return 1
case "info":
return 2
case "success":
return 3
default:
return 4
}
}
func log2File(level, msg string) {
switch level {
case "error":
z.Error(msg)
case "warning":
z.Warn(msg)
case "info", "success":
z.Info(msg)
default:
z.Debug(msg)
}
}
func level2AtomicLevel(level string) zap.AtomicLevel {
switch level {
case "error":
return zap.NewAtomicLevelAt(zap.ErrorLevel)
case "warning":
return zap.NewAtomicLevelAt(zap.WarnLevel)
case "info", "success":
return zap.NewAtomicLevelAt(zap.InfoLevel)
default:
return zap.NewAtomicLevelAt(zap.DebugLevel)
}
}
func init() {
InitAurora()
}
func Msg(level string, withoutColor, ln bool, msg ...interface{}) {
var message string
var confLevel, msgLevel int
if LuetCfg.GetGeneral().Debug {
confLevel = 3
} else {
confLevel = level2Number(LuetCfg.GetLogging().Level)
}
msgLevel = level2Number(level)
if msgLevel > confLevel {
return
}
for _, m := range msg {
message += " " + fmt.Sprintf("%v", m)
}
var levelMsg string
if withoutColor || !LuetCfg.GetLogging().Color {
levelMsg = message
} else {
switch level {
case "warning":
levelMsg = Yellow(":construction: warning" + message).BgBlack().String()
case "debug":
levelMsg = White(message).BgBlack().String()
case "info", "success":
levelMsg = message
case "error":
levelMsg = Red(message).String()
}
}
if LuetCfg.GetLogging().EnableEmoji {
levelMsg = emoji.Sprint(levelMsg)
} else {
re := regexp.MustCompile(`[:][\w]+[:]`)
levelMsg = re.ReplaceAllString(levelMsg, "")
}
if z != nil {
log2File(level, message)
}
if ln {
switch level {
case "info":
pterm.Info.Println(levelMsg)
case "success":
pterm.Success.Println(levelMsg)
case "warning":
pterm.Warning.Println(levelMsg)
case "error":
pterm.Error.Println(levelMsg)
case "fatal":
pterm.Fatal.Println(levelMsg)
default:
fmt.Println(levelMsg)
}
//
} else {
switch level {
case "success":
pterm.Success.Print(levelMsg)
case "info":
pterm.Info.Print(levelMsg)
case "warning":
pterm.Warning.Print(levelMsg)
case "error":
pterm.Error.Print(levelMsg)
case "fatal":
pterm.Fatal.Print(levelMsg)
default:
fmt.Print(levelMsg)
}
}
}
func Warning(mess ...interface{}) {
Msg("warning", false, true, mess...)
if LuetCfg.GetGeneral().FatalWarns {
os.Exit(2)
}
}
func Debug(mess ...interface{}) {
pc, file, line, ok := runtime.Caller(1)
if ok {
mess = append([]interface{}{fmt.Sprintf("DEBUG (%s:#%d:%v)",
path.Base(file), line, runtime.FuncForPC(pc).Name())}, mess...)
}
Msg("debug", false, true, mess...)
}
func DebugC(mess ...interface{}) {
Msg("debug", true, true, mess...)
}
func Info(mess ...interface{}) {
Msg("info", false, true, mess...)
}
func Success(mess ...interface{}) {
Msg("success", false, true, mess...)
}
func InfoC(mess ...interface{}) {
Msg("info", true, true, mess...)
}
func Error(mess ...interface{}) {
Msg("error", false, true, mess...)
}
func Fatal(mess ...interface{}) {
Error(mess...)
os.Exit(1)
}

View File

@ -18,14 +18,11 @@ package pkg_test
import ( import (
"testing" "testing"
. "github.com/mudler/luet/cmd/util"
. "github.com/onsi/ginkgo" . "github.com/onsi/ginkgo"
. "github.com/onsi/gomega" . "github.com/onsi/gomega"
) )
func TestSolver(t *testing.T) { func TestSolver(t *testing.T) {
RegisterFailHandler(Fail) RegisterFailHandler(Fail)
LoadConfig()
RunSpecs(t, "Package Suite") RunSpecs(t, "Package Suite")
} }

View File

@ -1,90 +0,0 @@
// Copyright © 2019 Ettore Di Giacinto <mudler@gentoo.org>
// Daniele Rondina <geaaru@sabayonlinux.org>
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, see <http://www.gnu.org/licenses/>.
package repository
import (
"io/ioutil"
"path"
"path/filepath"
"regexp"
"github.com/mudler/luet/pkg/api/core/types"
. "github.com/mudler/luet/pkg/config"
. "github.com/mudler/luet/pkg/logger"
)
func LoadRepositories(c *LuetConfig) error {
var regexRepo = regexp.MustCompile(`.yml$|.yaml$`)
var err error
rootfs := ""
// Respect the rootfs param on read repositories
if !c.ConfigFromHost {
rootfs, err = c.GetSystem().GetRootFsAbs()
if err != nil {
return err
}
}
for _, rdir := range c.RepositoriesConfDir {
rdir = filepath.Join(rootfs, rdir)
Debug("Parsing Repository Directory", rdir, "...")
files, err := ioutil.ReadDir(rdir)
if err != nil {
Debug("Skip dir", rdir, ":", err.Error())
continue
}
for _, file := range files {
if file.IsDir() {
continue
}
if !regexRepo.MatchString(file.Name()) {
Debug("File", file.Name(), "skipped.")
continue
}
content, err := ioutil.ReadFile(path.Join(rdir, file.Name()))
if err != nil {
Warning("On read file", file.Name(), ":", err.Error())
Warning("File", file.Name(), "skipped.")
continue
}
r, err := types.LoadRepository(content)
if err != nil {
Warning("On parse file", file.Name(), ":", err.Error())
Warning("File", file.Name(), "skipped.")
continue
}
if r.Name == "" || len(r.Urls) == 0 || r.Type == "" {
Warning("Invalid repository ", file.Name())
Warning("File", file.Name(), "skipped.")
continue
}
c.AddSystemRepository(*r)
}
}
return nil
}

View File

@ -1,55 +0,0 @@
// Copyright © 2019 Ettore Di Giacinto <mudler@gentoo.org>
// Daniele Rondina <geaaru@sabayonlinux.org>
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, see <http://www.gnu.org/licenses/>.
package repository_test
import (
. "github.com/mudler/luet/pkg/config"
. "github.com/mudler/luet/pkg/repository"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
var _ = Describe("Repository", func() {
Context("Load Repository1", func() {
cfg := &LuetConfig{}
cfg.RepositoriesConfDir = []string{
"../../tests/fixtures/repos.conf.d",
}
err := LoadRepositories(cfg)
It("Chec Load Repository 1", func() {
Expect(err).Should(BeNil())
Expect(len(cfg.SystemRepositories)).Should(Equal(2))
Expect(cfg.SystemRepositories[0].Name).Should(Equal("test1"))
Expect(cfg.SystemRepositories[0].Priority).Should(Equal(999))
Expect(cfg.SystemRepositories[0].Type).Should(Equal("disk"))
Expect(len(cfg.SystemRepositories[0].Urls)).Should(Equal(1))
Expect(cfg.SystemRepositories[0].Urls[0]).Should(Equal("tests/repos/test1"))
})
It("Chec Load Repository 2", func() {
Expect(err).Should(BeNil())
Expect(len(cfg.SystemRepositories)).Should(Equal(2))
Expect(cfg.SystemRepositories[1].Name).Should(Equal("test2"))
Expect(cfg.SystemRepositories[1].Priority).Should(Equal(1000))
Expect(cfg.SystemRepositories[1].Type).Should(Equal("disk"))
Expect(len(cfg.SystemRepositories[1].Urls)).Should(Equal(1))
Expect(cfg.SystemRepositories[1].Urls[0]).Should(Equal("tests/repos/test2"))
})
})
})

View File

@ -18,14 +18,11 @@ package solver_test
import ( import (
"testing" "testing"
. "github.com/mudler/luet/cmd/util"
. "github.com/onsi/ginkgo" . "github.com/onsi/ginkgo"
. "github.com/onsi/gomega" . "github.com/onsi/gomega"
) )
func TestSolver(t *testing.T) { func TestSolver(t *testing.T) {
RegisterFailHandler(Fail) RegisterFailHandler(Fail)
LoadConfig()
RunSpecs(t, "Solver Suite") RunSpecs(t, "Solver Suite")
} }

View File

@ -19,14 +19,11 @@ package spectooling_test
import ( import (
"testing" "testing"
. "github.com/mudler/luet/cmd/util"
. "github.com/onsi/ginkgo" . "github.com/onsi/ginkgo"
. "github.com/onsi/gomega" . "github.com/onsi/gomega"
) )
func TestSolver(t *testing.T) { func TestSolver(t *testing.T) {
RegisterFailHandler(Fail) RegisterFailHandler(Fail)
LoadConfig()
RunSpecs(t, "Spec Tooling Suite") RunSpecs(t, "Spec Tooling Suite")
} }

View File

@ -18,14 +18,11 @@ package tree_test
import ( import (
"testing" "testing"
. "github.com/mudler/luet/cmd/util"
. "github.com/onsi/ginkgo" . "github.com/onsi/ginkgo"
. "github.com/onsi/gomega" . "github.com/onsi/gomega"
) )
func TestTree(t *testing.T) { func TestTree(t *testing.T) {
RegisterFailHandler(Fail) RegisterFailHandler(Fail)
LoadConfig()
RunSpecs(t, "Tree Suite") RunSpecs(t, "Tree Suite")
} }

View File

@ -18,14 +18,11 @@ package version_test
import ( import (
"testing" "testing"
. "github.com/mudler/luet/cmd/util"
. "github.com/onsi/ginkgo" . "github.com/onsi/ginkgo"
. "github.com/onsi/gomega" . "github.com/onsi/gomega"
) )
func TestVersioner(t *testing.T) { func TestVersioner(t *testing.T) {
RegisterFailHandler(Fail) RegisterFailHandler(Fail)
LoadConfig()
RunSpecs(t, "Versioner Suite") RunSpecs(t, "Versioner Suite")
} }

View File

@ -66,6 +66,7 @@ testInstall() {
testReInstall() { testReInstall() {
output=$(luet install -y --config $tmpdir/luet.yaml test/c@1.0) output=$(luet install -y --config $tmpdir/luet.yaml test/c@1.0)
echo "$output"
installst=$? installst=$?
assertEquals 'install test successfully' "$installst" "0" assertEquals 'install test successfully' "$installst" "0"
assertContains 'contains warning' "$output" 'No packages to install' assertContains 'contains warning' "$output" 'No packages to install'