🎨 Introduce contextualized logging

This commit is multi-fold as it also refactors internally context and logger
as interfaces so it is easier to plug luet as a library externally.

Introduces a garbage collector (related to #227) but doesn't handle yet
parallelism.

Closes #265
This commit is contained in:
Ettore Di Giacinto 2021-12-17 15:21:03 +01:00
parent fd90e0d627
commit c98f427156
105 changed files with 2672 additions and 1271 deletions

View File

@ -31,7 +31,6 @@ import (
"github.com/mudler/luet/pkg/compiler/types/options"
fileHelpers "github.com/mudler/luet/pkg/helpers/file"
pkg "github.com/mudler/luet/pkg/package"
"github.com/mudler/luet/pkg/solver"
tree "github.com/mudler/luet/pkg/tree"
"github.com/spf13/cobra"
@ -39,6 +38,10 @@ import (
)
var buildCmd = &cobra.Command{
// Skip processing output
Annotations: map[string]string{
util.CommandProcessOutput: "",
},
Use: "build <package name> <package name> <package name> ...",
Short: "build a package or a tree",
Long: `Builds one or more packages from a tree (current directory is implied):
@ -83,8 +86,6 @@ Build packages specifying multiple definition trees:
viper.BindPFlag("wait", cmd.Flags().Lookup("wait"))
viper.BindPFlag("keep-images", cmd.Flags().Lookup("keep-images"))
util.BindSolverFlags(cmd)
viper.BindPFlag("general.show_build_output", cmd.Flags().Lookup("live-output"))
viper.BindPFlag("backend-args", cmd.Flags().Lookup("backend-args"))
@ -93,7 +94,7 @@ Build packages specifying multiple definition trees:
treePaths := viper.GetStringSlice("tree")
dst := viper.GetString("destination")
concurrency := util.DefaultContext.Config.GetGeneral().Concurrency
concurrency := util.DefaultContext.Config.General.Concurrency
backendType := viper.GetString("backend")
privileged := viper.GetBool("privileged")
revdeps := viper.GetBool("revdeps")
@ -116,11 +117,7 @@ Build packages specifying multiple definition trees:
var results Results
backendArgs := viper.GetStringSlice("backend-args")
out, _ := cmd.Flags().GetString("output")
if out != "terminal" {
util.DefaultContext.Config.GetLogging().SetLogLevel("error")
}
pretend, _ := cmd.Flags().GetBool("pretend")
fromRepo, _ := cmd.Flags().GetBool("from-repositories")
@ -153,15 +150,11 @@ Build packages specifying multiple definition trees:
util.DefaultContext.Debug("Creating destination folder", dst)
}
opts := util.SetSolverConfig(util.DefaultContext)
opts := util.DefaultContext.GetConfig().Solver
pullRepo, _ := cmd.Flags().GetStringArray("pull-repository")
util.DefaultContext.Config.GetGeneral().ShowBuildOutput = viper.GetBool("general.show_build_output")
util.DefaultContext.Debug("Solver", opts.CompactString())
opts.Options = solver.Options{Type: solver.SingleCoreSimple, Concurrency: concurrency}
compileropts := []options.Option{options.NoDeps(nodeps),
options.WithBackendType(backendType),
options.PushImages(push),
@ -170,7 +163,7 @@ Build packages specifying multiple definition trees:
options.WithPushRepository(imageRepository),
options.Rebuild(rebuild),
options.WithTemplateFolder(util.TemplateFolders(util.DefaultContext, fromRepo, treePaths)),
options.WithSolverOptions(*opts),
options.WithSolverOptions(opts),
options.Wait(wait),
options.OnlyTarget(onlyTarget),
options.PullFirst(pull),
@ -341,7 +334,7 @@ func init() {
buildCmd.Flags().Float32("solver-discount", 1.0, "Solver discount rate")
buildCmd.Flags().Int("solver-attempts", 9000, "Solver maximum attempts")
buildCmd.Flags().Bool("solver-concurrent", false, "Use concurrent solver (experimental)")
buildCmd.Flags().Bool("live-output", util.DefaultContext.Config.GetGeneral().ShowBuildOutput, "Enable live output of the build phase.")
buildCmd.Flags().Bool("live-output", true, "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("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")

View File

@ -31,16 +31,13 @@ var cleanupCmd = &cobra.Command{
Use: "cleanup",
Short: "Clean packages cache.",
Long: `remove downloaded packages tarballs and clean cache directory`,
PreRun: func(cmd *cobra.Command, args []string) {
util.BindSystemFlags(cmd)
},
Run: func(cmd *cobra.Command, args []string) {
var cleaned int = 0
util.SetSystemConfig(util.DefaultContext)
// Check if cache dir exists
if fileHelper.Exists(util.DefaultContext.Config.GetSystem().GetSystemPkgsCacheDirPath()) {
if fileHelper.Exists(util.DefaultContext.Config.System.PkgsCachePath) {
files, err := ioutil.ReadDir(util.DefaultContext.Config.GetSystem().GetSystemPkgsCacheDirPath())
files, err := ioutil.ReadDir(util.DefaultContext.Config.System.PkgsCachePath)
if err != nil {
util.DefaultContext.Fatal("Error on read cachedir ", err.Error())
}
@ -50,7 +47,7 @@ var cleanupCmd = &cobra.Command{
util.DefaultContext.Debug("Removing ", file.Name())
err := os.RemoveAll(
filepath.Join(util.DefaultContext.Config.GetSystem().GetSystemPkgsCacheDirPath(), file.Name()))
filepath.Join(util.DefaultContext.Config.System.PkgsCachePath, file.Name()))
if err != nil {
util.DefaultContext.Fatal("Error on removing", file.Name())
}
@ -58,14 +55,11 @@ var cleanupCmd = &cobra.Command{
}
}
util.DefaultContext.Info(fmt.Sprintf("Cleaned: %d files from %s", cleaned, util.DefaultContext.Config.GetSystem().GetSystemPkgsCacheDirPath()))
util.DefaultContext.Info(fmt.Sprintf("Cleaned: %d files from %s", cleaned, util.DefaultContext.Config.System.PkgsCachePath))
},
}
func init() {
cleanupCmd.Flags().String("system-dbpath", "", "System db path")
cleanupCmd.Flags().String("system-target", "", "System rootpath")
cleanupCmd.Flags().String("system-engine", "", "System DB engine")
RootCmd.AddCommand(cleanupCmd)
}

View File

@ -27,7 +27,7 @@ import (
)
func NewDatabaseCreateCommand() *cobra.Command {
var ans = &cobra.Command{
return &cobra.Command{
Use: "create <artifact_metadata1.yaml> <artifact_metadata1.yaml>",
Short: "Insert a package in the system DB",
Long: `Inserts a package in the system database:
@ -42,12 +42,8 @@ The yaml must contain the package definition, and the file list at least.
For reference, inspect a "metadata.yaml" file generated while running "luet build"`,
Args: cobra.OnlyValidArgs,
PreRun: func(cmd *cobra.Command, args []string) {
util.BindSystemFlags(cmd)
},
Run: func(cmd *cobra.Command, args []string) {
util.SetSystemConfig(util.DefaultContext)
systemDB := util.DefaultContext.Config.GetSystemDB()
for _, a := range args {
@ -81,9 +77,4 @@ For reference, inspect a "metadata.yaml" file generated while running "luet buil
},
}
ans.Flags().String("system-dbpath", "", "System db path")
ans.Flags().String("system-target", "", "System rootpath")
ans.Flags().String("system-engine", "", "System DB engine")
return ans
}

View File

@ -36,12 +36,9 @@ func NewDatabaseGetCommand() *cobra.Command {
To return also files:
$ luet database get --files system/foo`,
Args: cobra.OnlyValidArgs,
PreRun: func(cmd *cobra.Command, args []string) {
util.BindSystemFlags(cmd)
},
Run: func(cmd *cobra.Command, args []string) {
showFiles, _ := cmd.Flags().GetBool("files")
util.SetSystemConfig(util.DefaultContext)
systemDB := util.DefaultContext.Config.GetSystemDB()
@ -77,9 +74,6 @@ To return also files:
},
}
c.Flags().Bool("files", false, "Show package files.")
c.Flags().String("system-dbpath", "", "System db path")
c.Flags().String("system-target", "", "System rootpath")
c.Flags().String("system-engine", "", "System DB engine")
return c
}

View File

@ -23,7 +23,7 @@ import (
)
func NewDatabaseRemoveCommand() *cobra.Command {
var ans = &cobra.Command{
return &cobra.Command{
Use: "remove [package1] [package2] ...",
Short: "Remove a package from the system DB (forcefully - you normally don't want to do that)",
Long: `Removes a package in the system database without actually uninstalling it:
@ -33,11 +33,8 @@ func NewDatabaseRemoveCommand() *cobra.Command {
This commands takes multiple packages as arguments and prunes their entries from the system database.
`,
Args: cobra.OnlyValidArgs,
PreRun: func(cmd *cobra.Command, args []string) {
util.BindSystemFlags(cmd)
},
Run: func(cmd *cobra.Command, args []string) {
util.SetSystemConfig(util.DefaultContext)
systemDB := util.DefaultContext.Config.GetSystemDB()
@ -58,9 +55,5 @@ This commands takes multiple packages as arguments and prunes their entries from
},
}
ans.Flags().String("system-dbpath", "", "System db path")
ans.Flags().String("system-target", "", "System rootpath")
ans.Flags().String("system-engine", "", "System DB engine")
return ans
}

View File

@ -15,9 +15,7 @@
package cmd
import (
"github.com/mudler/luet/pkg/api/core/types"
installer "github.com/mudler/luet/pkg/installer"
"github.com/mudler/luet/pkg/solver"
helpers "github.com/mudler/luet/cmd/helpers"
"github.com/mudler/luet/cmd/util"
@ -48,8 +46,6 @@ To force install a package:
`,
Aliases: []string{"i"},
PreRun: func(cmd *cobra.Command, args []string) {
util.BindSystemFlags(cmd)
util.BindSolverFlags(cmd)
viper.BindPFlag("onlydeps", cmd.Flags().Lookup("onlydeps"))
viper.BindPFlag("nodeps", cmd.Flags().Lookup("nodeps"))
viper.BindPFlag("force", cmd.Flags().Lookup("force"))
@ -71,28 +67,13 @@ To force install a package:
onlydeps := viper.GetBool("onlydeps")
yes := viper.GetBool("yes")
downloadOnly, _ := cmd.Flags().GetBool("download-only")
finalizerEnvs, _ := cmd.Flags().GetStringArray("finalizer-env")
relax, _ := cmd.Flags().GetBool("relax")
util.SetSystemConfig(util.DefaultContext)
util.SetSolverConfig(util.DefaultContext)
util.DefaultContext.Config.GetSolverOptions().Implementation = solver.SingleCoreSimple
util.DefaultContext.Debug("Solver", util.DefaultContext.Config.GetSolverOptions().CompactString())
// Load config protect configs
util.DefaultContext.Config.LoadConfigProtect(util.DefaultContext)
// Load finalizer runtime environments
err := util.SetCliFinalizerEnvs(util.DefaultContext, finalizerEnvs)
if err != nil {
util.DefaultContext.Fatal(err.Error())
}
util.DefaultContext.Debug("Solver", util.DefaultContext.Config.Solver.CompactString())
inst := installer.NewLuetInstaller(installer.LuetInstallerOptions{
Concurrency: util.DefaultContext.Config.GetGeneral().Concurrency,
SolverOptions: *util.DefaultContext.Config.GetSolverOptions(),
Concurrency: util.DefaultContext.Config.General.Concurrency,
SolverOptions: util.DefaultContext.Config.Solver,
NoDeps: nodeps,
Force: force,
OnlyDeps: onlydeps,
@ -104,8 +85,11 @@ To force install a package:
Context: util.DefaultContext,
})
system := &installer.System{Database: util.DefaultContext.Config.GetSystemDB(), Target: util.DefaultContext.Config.GetSystem().Rootfs}
err = inst.Install(toInstall, system)
system := &installer.System{
Database: util.DefaultContext.Config.GetSystemDB(),
Target: util.DefaultContext.Config.System.Rootfs,
}
err := inst.Install(toInstall, system)
if err != nil {
util.DefaultContext.Fatal("Error: " + err.Error())
}
@ -113,14 +97,7 @@ To force install a package:
}
func init() {
installCmd.Flags().String("system-dbpath", "", "System db path")
installCmd.Flags().String("system-target", "", "System rootpath")
installCmd.Flags().String("system-engine", "", "System DB engine")
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-discount", 1.0, "Solver discount rate")
installCmd.Flags().Int("solver-attempts", 9000, "Solver maximum attempts")
installCmd.Flags().Bool("nodeps", false, "Don't consider package dependencies (harmful!)")
installCmd.Flags().Bool("relax", false, "Relax installation constraints")

View File

@ -19,10 +19,8 @@ import (
"os"
"strings"
"github.com/mudler/luet/pkg/api/core/types"
installer "github.com/mudler/luet/pkg/installer"
pkg "github.com/mudler/luet/pkg/package"
"github.com/mudler/luet/pkg/solver"
"github.com/mudler/luet/cmd/util"
@ -43,8 +41,6 @@ To reinstall packages in the list:
`,
Aliases: []string{"i"},
PreRun: func(cmd *cobra.Command, args []string) {
util.BindSystemFlags(cmd)
util.BindSolverFlags(cmd)
viper.BindPFlag("onlydeps", cmd.Flags().Lookup("onlydeps"))
viper.BindPFlag("nodeps", cmd.Flags().Lookup("nodeps"))
viper.BindPFlag("force", cmd.Flags().Lookup("force"))
@ -57,9 +53,11 @@ To reinstall packages in the list:
yes := viper.GetBool("yes")
downloadOnly, _ := cmd.Flags().GetBool("download-only")
util.SetSystemConfig(util.DefaultContext)
system := &installer.System{Database: util.DefaultContext.Config.GetSystemDB(), Target: util.DefaultContext.Config.GetSystem().Rootfs}
system := &installer.System{
Database: util.DefaultContext.Config.GetSystemDB(),
Target: util.DefaultContext.Config.System.Rootfs,
}
packs := system.OSCheck()
if !util.DefaultContext.Config.General.Quiet {
if len(packs) == 0 {
@ -90,18 +88,11 @@ To reinstall packages in the list:
toInstall = append(toInstall, new)
}
util.SetSolverConfig(util.DefaultContext)
util.DefaultContext.Config.GetSolverOptions().Implementation = solver.SingleCoreSimple
util.DefaultContext.Debug("Solver", util.DefaultContext.Config.GetSolverOptions().CompactString())
// Load config protect configs
util.DefaultContext.Config.LoadConfigProtect(util.DefaultContext)
util.DefaultContext.Debug("Solver", util.DefaultContext.Config.Solver.CompactString())
inst := installer.NewLuetInstaller(installer.LuetInstallerOptions{
Concurrency: util.DefaultContext.Config.GetGeneral().Concurrency,
SolverOptions: *util.DefaultContext.Config.GetSolverOptions(),
Concurrency: util.DefaultContext.Config.General.Concurrency,
SolverOptions: util.DefaultContext.Config.Solver,
NoDeps: true,
Force: force,
OnlyDeps: onlydeps,
@ -121,18 +112,11 @@ To reinstall packages in the list:
}
func init() {
osCheckCmd.Flags().String("system-dbpath", "", "System db path")
osCheckCmd.Flags().String("system-target", "", "System rootpath")
osCheckCmd.Flags().String("system-engine", "", "System DB engine")
osCheckCmd.Flags().Bool("reinstall", false, "reinstall")
osCheckCmd.Flags().String("solver-type", "", "Solver strategy ( Defaults none, available: "+types.AvailableResolvers+" )")
osCheckCmd.Flags().Float32("solver-rate", 0.7, "Solver learning rate")
osCheckCmd.Flags().Float32("solver-discount", 1.0, "Solver discount rate")
osCheckCmd.Flags().Int("solver-attempts", 9000, "Solver maximum attempts")
osCheckCmd.Flags().Bool("onlydeps", false, "Consider **only** package dependencies")
osCheckCmd.Flags().Bool("force", false, "Skip errors and keep going (potentially harmful)")
osCheckCmd.Flags().Bool("solver-concurrent", false, "Use concurrent solver (experimental)")
osCheckCmd.Flags().BoolP("yes", "y", false, "Don't ask questions")
osCheckCmd.Flags().Bool("download-only", false, "Download only")

View File

@ -52,7 +52,7 @@ Afterwards, you can use the content generated and associate it with a tree and a
dst := viper.GetString("destination")
compressionType := viper.GetString("compression")
concurrency := util.DefaultContext.Config.GetGeneral().Concurrency
concurrency := util.DefaultContext.Config.General.Concurrency
if len(args) != 1 {
util.DefaultContext.Fatal("You must specify a package name")

View File

@ -26,7 +26,6 @@ var reclaimCmd = &cobra.Command{
Use: "reclaim",
Short: "Reclaim packages to Luet database from available repositories",
PreRun: func(cmd *cobra.Command, args []string) {
util.BindSystemFlags(cmd)
viper.BindPFlag("force", cmd.Flags().Lookup("force"))
},
Long: `Reclaim tries to find association between packages in the online repositories and the system one.
@ -36,21 +35,23 @@ 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.
`,
Run: func(cmd *cobra.Command, args []string) {
util.SetSystemConfig(util.DefaultContext)
force := viper.GetBool("force")
util.DefaultContext.Debug("Solver", util.DefaultContext.Config.GetSolverOptions().CompactString())
util.DefaultContext.Debug("Solver", util.DefaultContext.Config.Solver.CompactString())
inst := installer.NewLuetInstaller(installer.LuetInstallerOptions{
Concurrency: util.DefaultContext.Config.GetGeneral().Concurrency,
Concurrency: util.DefaultContext.Config.General.Concurrency,
Force: force,
PreserveSystemEssentialData: true,
PackageRepositories: util.DefaultContext.Config.SystemRepositories,
Context: util.DefaultContext,
})
system := &installer.System{Database: util.DefaultContext.Config.GetSystemDB(), Target: util.DefaultContext.Config.GetSystem().Rootfs}
system := &installer.System{
Database: util.DefaultContext.Config.GetSystemDB(),
Target: util.DefaultContext.Config.System.Rootfs,
}
err := inst.Reclaim(system)
if err != nil {
util.DefaultContext.Fatal("Error: " + err.Error())
@ -60,10 +61,6 @@ It scans the target file system, and if finds a match with a package available i
func init() {
reclaimCmd.Flags().String("system-dbpath", "", "System db path")
reclaimCmd.Flags().String("system-target", "", "System rootpath")
reclaimCmd.Flags().String("system-engine", "", "System DB engine")
reclaimCmd.Flags().Bool("force", false, "Skip errors and keep going (potentially harmful)")
RootCmd.AddCommand(reclaimCmd)

View File

@ -15,9 +15,7 @@
package cmd
import (
"github.com/mudler/luet/pkg/api/core/types"
installer "github.com/mudler/luet/pkg/installer"
"github.com/mudler/luet/pkg/solver"
helpers "github.com/mudler/luet/cmd/helpers"
"github.com/mudler/luet/cmd/util"
@ -35,8 +33,6 @@ var reinstallCmd = &cobra.Command{
$ luet reinstall -y system/busybox shells/bash system/coreutils ...
`,
PreRun: func(cmd *cobra.Command, args []string) {
util.BindSystemFlags(cmd)
util.BindSolverFlags(cmd)
viper.BindPFlag("onlydeps", cmd.Flags().Lookup("onlydeps"))
viper.BindPFlag("force", cmd.Flags().Lookup("force"))
viper.BindPFlag("for", cmd.Flags().Lookup("for"))
@ -54,20 +50,11 @@ var reinstallCmd = &cobra.Command{
downloadOnly, _ := cmd.Flags().GetBool("download-only")
installed, _ := cmd.Flags().GetBool("installed")
util.SetSystemConfig(util.DefaultContext)
util.SetSolverConfig(util.DefaultContext)
util.DefaultContext.Config.GetSolverOptions().Implementation = solver.SingleCoreSimple
util.DefaultContext.Debug("Solver", util.DefaultContext.Config.GetSolverOptions().CompactString())
// Load config protect configs
util.DefaultContext.Config.LoadConfigProtect(util.DefaultContext)
util.DefaultContext.Debug("Solver", util.DefaultContext.Config.Solver.CompactString())
inst := installer.NewLuetInstaller(installer.LuetInstallerOptions{
Concurrency: util.DefaultContext.Config.GetGeneral().Concurrency,
SolverOptions: *util.DefaultContext.Config.GetSolverOptions(),
Concurrency: util.DefaultContext.Config.General.Concurrency,
SolverOptions: util.DefaultContext.Config.Solver,
NoDeps: true,
Force: force,
OnlyDeps: onlydeps,
@ -78,7 +65,7 @@ var reinstallCmd = &cobra.Command{
PackageRepositories: util.DefaultContext.Config.SystemRepositories,
})
system := &installer.System{Database: util.DefaultContext.Config.GetSystemDB(), Target: util.DefaultContext.Config.GetSystem().Rootfs}
system := &installer.System{Database: util.DefaultContext.Config.GetSystemDB(), Target: util.DefaultContext.Config.System.Rootfs}
if installed {
for _, p := range system.Database.World() {
@ -106,18 +93,8 @@ var reinstallCmd = &cobra.Command{
}
func init() {
reinstallCmd.Flags().String("system-dbpath", "", "System db path")
reinstallCmd.Flags().String("system-target", "", "System rootpath")
reinstallCmd.Flags().String("system-engine", "", "System DB engine")
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-discount", 1.0, "Solver discount rate")
reinstallCmd.Flags().Int("solver-attempts", 9000, "Solver maximum attempts")
reinstallCmd.Flags().Bool("onlydeps", false, "Consider **only** package dependencies")
reinstallCmd.Flags().Bool("force", false, "Skip errors and keep going (potentially harmful)")
reinstallCmd.Flags().Bool("solver-concurrent", false, "Use concurrent solver (experimental)")
reinstallCmd.Flags().Bool("installed", false, "Reinstall installed packages")
reinstallCmd.Flags().BoolP("yes", "y", false, "Don't ask questions")
reinstallCmd.Flags().Bool("download-only", false, "Download only")

View File

@ -15,7 +15,6 @@
package cmd
import (
"github.com/mudler/luet/pkg/api/core/types"
installer "github.com/mudler/luet/pkg/installer"
"github.com/mudler/luet/pkg/solver"
@ -37,8 +36,6 @@ var replaceCmd = &cobra.Command{
$ luet replace -y system/busybox ... --for shells/bash --for system/coreutils ...
`,
PreRun: func(cmd *cobra.Command, args []string) {
util.BindSystemFlags(cmd)
util.BindSolverFlags(cmd)
viper.BindPFlag("onlydeps", cmd.Flags().Lookup("onlydeps"))
viper.BindPFlag("nodeps", cmd.Flags().Lookup("nodeps"))
viper.BindPFlag("force", cmd.Flags().Lookup("force"))
@ -57,8 +54,6 @@ var replaceCmd = &cobra.Command{
yes := viper.GetBool("yes")
downloadOnly, _ := cmd.Flags().GetBool("download-only")
util.SetSystemConfig(util.DefaultContext)
util.SetSolverConfig(util.DefaultContext)
for _, a := range args {
pack, err := helpers.ParsePackageStr(a)
if err != nil {
@ -75,16 +70,13 @@ var replaceCmd = &cobra.Command{
toAdd = append(toAdd, pack)
}
util.DefaultContext.Config.GetSolverOptions().Implementation = solver.SingleCoreSimple
util.DefaultContext.Config.Solver.Implementation = solver.SingleCoreSimple
util.DefaultContext.Debug("Solver", util.DefaultContext.Config.GetSolverOptions().CompactString())
// Load config protect configs
util.DefaultContext.Config.LoadConfigProtect(util.DefaultContext)
util.DefaultContext.Debug("Solver", util.DefaultContext.Config.Solver.CompactString())
inst := installer.NewLuetInstaller(installer.LuetInstallerOptions{
Concurrency: util.DefaultContext.Config.GetGeneral().Concurrency,
SolverOptions: *util.DefaultContext.Config.GetSolverOptions(),
Concurrency: util.DefaultContext.Config.General.Concurrency,
SolverOptions: util.DefaultContext.Config.Solver,
NoDeps: nodeps,
Force: force,
OnlyDeps: onlydeps,
@ -95,7 +87,7 @@ var replaceCmd = &cobra.Command{
Context: util.DefaultContext,
})
system := &installer.System{Database: util.DefaultContext.Config.GetSystemDB(), Target: util.DefaultContext.Config.GetSystem().Rootfs}
system := &installer.System{Database: util.DefaultContext.Config.GetSystemDB(), Target: util.DefaultContext.Config.System.Rootfs}
err := inst.Swap(toUninstall, toAdd, system)
if err != nil {
util.DefaultContext.Fatal("Error: " + err.Error())
@ -105,18 +97,9 @@ var replaceCmd = &cobra.Command{
func init() {
replaceCmd.Flags().String("system-dbpath", "", "System db path")
replaceCmd.Flags().String("system-target", "", "System rootpath")
replaceCmd.Flags().String("system-engine", "", "System DB engine")
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-discount", 1.0, "Solver discount rate")
replaceCmd.Flags().Int("solver-attempts", 9000, "Solver maximum attempts")
replaceCmd.Flags().Bool("nodeps", false, "Don't consider package dependencies (harmful!)")
replaceCmd.Flags().Bool("onlydeps", false, "Consider **only** package dependencies")
replaceCmd.Flags().Bool("force", false, "Skip errors and keep going (potentially harmful)")
replaceCmd.Flags().Bool("solver-concurrent", false, "Use concurrent solver (experimental)")
replaceCmd.Flags().BoolP("yes", "y", false, "Don't ask questions")
replaceCmd.Flags().StringSlice("for", []string{}, "Packages that has to be installed in place of others")
replaceCmd.Flags().Bool("download-only", false, "Download only")

View File

@ -68,7 +68,7 @@ func NewRepoListCommand() *cobra.Command {
repoText = pterm.LightYellow(repo.Urls[0])
}
repobasedir := util.DefaultContext.Config.GetSystem().GetRepoDatabaseDirPath(repo.Name)
repobasedir := util.DefaultContext.Config.System.GetRepoDatabaseDirPath(repo.Name)
if repo.Cached {
r := installer.NewSystemRepository(repo)

View File

@ -81,19 +81,15 @@ To build a package, from a tree definition:
`,
Version: version(),
PersistentPreRun: func(cmd *cobra.Command, args []string) {
err := util.InitContext(util.DefaultContext)
ctx, err := util.InitContext(cmd)
if err != nil {
util.DefaultContext.Error("failed to load configuration:", err.Error())
fmt.Println("failed to load configuration:", err.Error())
os.Exit(1)
}
util.DisplayVersionBanner(util.DefaultContext, util.IntroScreen, version, license)
// Initialize tmpdir prefix. TODO: Move this with LoadConfig
// directly on sub command to ensure the creation only when it's
// needed.
err = util.DefaultContext.Config.GetSystem().InitTmpDir()
if err != nil {
util.DefaultContext.Fatal("failed on init tmp basedir:", err.Error())
}
util.DefaultContext = ctx
util.DisplayVersionBanner(util.DefaultContext, util.IntroScreen, version, license)
viper.BindPFlag("plugin", cmd.Flags().Lookup("plugin"))
@ -109,7 +105,7 @@ To build a package, from a tree definition:
},
PersistentPostRun: func(cmd *cobra.Command, args []string) {
// Cleanup all tmp directories used by luet
err := util.DefaultContext.Config.GetSystem().CleanupTmpDir()
err := util.DefaultContext.Clean()
if err != nil {
util.DefaultContext.Warning("failed on cleanup tmpdir:", err.Error())
}
@ -129,5 +125,5 @@ func Execute() {
}
func init() {
util.InitViper(util.DefaultContext, RootCmd)
util.InitViper(RootCmd)
}

View File

@ -20,7 +20,6 @@ import (
"github.com/ghodss/yaml"
"github.com/mudler/luet/cmd/util"
"github.com/mudler/luet/pkg/api/core/types"
installer "github.com/mudler/luet/pkg/installer"
pkg "github.com/mudler/luet/pkg/package"
"github.com/pterm/pterm"
@ -86,7 +85,7 @@ func packageToList(l *util.ListWriter, repo string, p pkg.Package) {
func searchLocally(term string, l *util.ListWriter, t *util.TableWriter, label, labelMatch, revdeps, hidden bool) Results {
var results Results
system := &installer.System{Database: util.DefaultContext.Config.GetSystemDB(), Target: util.DefaultContext.Config.GetSystem().Rootfs}
system := &installer.System{Database: util.DefaultContext.Config.GetSystemDB(), Target: util.DefaultContext.Config.System.Rootfs}
var err error
iMatches := pkg.Packages{}
@ -148,8 +147,8 @@ func searchOnline(term string, l *util.ListWriter, t *util.TableWriter, label, l
inst := installer.NewLuetInstaller(
installer.LuetInstallerOptions{
Concurrency: util.DefaultContext.Config.GetGeneral().Concurrency,
SolverOptions: *util.DefaultContext.Config.GetSolverOptions(),
Concurrency: util.DefaultContext.Config.General.Concurrency,
SolverOptions: util.DefaultContext.Config.Solver,
PackageRepositories: util.DefaultContext.Config.SystemRepositories,
Context: util.DefaultContext,
},
@ -238,8 +237,8 @@ func searchFiles(term string, l *util.ListWriter, t *util.TableWriter) Results {
inst := installer.NewLuetInstaller(
installer.LuetInstallerOptions{
Concurrency: util.DefaultContext.Config.GetGeneral().Concurrency,
SolverOptions: *util.DefaultContext.Config.GetSolverOptions(),
Concurrency: util.DefaultContext.Config.General.Concurrency,
SolverOptions: util.DefaultContext.Config.Solver,
PackageRepositories: util.DefaultContext.Config.SystemRepositories,
Context: util.DefaultContext,
},
@ -272,7 +271,11 @@ func searchFiles(term string, l *util.ListWriter, t *util.TableWriter) Results {
}
var searchCmd = &cobra.Command{
Use: "search <term>",
Use: "search <term>",
// Skip processing output
Annotations: map[string]string{
util.CommandProcessOutput: "",
},
Short: "Search packages",
Long: `Search for installed and available packages
@ -309,8 +312,7 @@ Search can also return results in the terminal in different ways: as terminal ou
`,
Aliases: []string{"s"},
PreRun: func(cmd *cobra.Command, args []string) {
util.BindSystemFlags(cmd)
util.BindSolverFlags(cmd)
viper.BindPFlag("installed", cmd.Flags().Lookup("installed"))
},
Run: func(cmd *cobra.Command, args []string) {
@ -329,18 +331,11 @@ Search can also return results in the terminal in different ways: as terminal ou
tableMode, _ := cmd.Flags().GetBool("table")
files, _ := cmd.Flags().GetBool("files")
util.SetSystemConfig(util.DefaultContext)
util.SetSolverConfig(util.DefaultContext)
out, _ := cmd.Flags().GetString("output")
if out != "terminal" {
util.DefaultContext.Config.GetLogging().SetLogLevel(types.FatalLevel)
}
l := &util.ListWriter{}
t := &util.TableWriter{}
t.AppendRow(rows)
util.DefaultContext.Debug("Solver", util.DefaultContext.Config.GetSolverOptions().CompactString())
util.DefaultContext.Debug("Solver", util.DefaultContext.Config.Solver.CompactString())
switch {
case files && installed:
@ -383,16 +378,9 @@ Search can also return results in the terminal in different ways: as terminal ou
}
func init() {
searchCmd.Flags().String("system-dbpath", "", "System db path")
searchCmd.Flags().String("system-target", "", "System rootpath")
searchCmd.Flags().String("system-engine", "", "System DB engine")
searchCmd.Flags().Bool("installed", false, "Search between system packages")
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().Float32("solver-rate", 0.7, "Solver learning rate")
searchCmd.Flags().Float32("solver-discount", 1.0, "Solver discount rate")
searchCmd.Flags().Int("solver-attempts", 9000, "Solver maximum attempts")
searchCmd.Flags().Bool("by-label", false, "Search packages through label")
searchCmd.Flags().Bool("by-label-regex", false, "Search packages through label regex")
searchCmd.Flags().Bool("revdeps", false, "Search package reverse dependencies")

View File

@ -38,7 +38,11 @@ import (
func NewTreeImageCommand() *cobra.Command {
var ans = &cobra.Command{
Use: "images [OPTIONS]",
Use: "images [OPTIONS]",
// Skip processing output
Annotations: map[string]string{
util.CommandProcessOutput: "",
},
Short: "List of the images of a package",
PreRun: func(cmd *cobra.Command, args []string) {
t, _ := cmd.Flags().GetStringArray("tree")
@ -60,12 +64,7 @@ func NewTreeImageCommand() *cobra.Command {
imageRepository := viper.GetString("image-repository")
pullRepo, _ := cmd.Flags().GetStringArray("pull-repository")
values := util.ValuesFlags()
out, _ := cmd.Flags().GetString("output")
if out != "terminal" {
util.DefaultContext.Config.GetLogging().SetLogLevel("error")
}
reciper := tree.NewCompilerRecipe(pkg.NewInMemoryDatabase(false))
for _, t := range treePath {
@ -76,7 +75,7 @@ func NewTreeImageCommand() *cobra.Command {
}
compilerBackend := backend.NewSimpleDockerBackend(util.DefaultContext)
opts := *util.DefaultContext.Config.GetSolverOptions()
opts := util.DefaultContext.Config.Solver
opts.Options = solver.Options{Type: solver.SingleCoreSimple, Concurrency: 1}
luetCompiler := compiler.NewLuetCompiler(
compilerBackend,

View File

@ -67,6 +67,10 @@ func NewTreePkglistCommand() *cobra.Command {
var matches []string
var ans = &cobra.Command{
// Skip processing output
Annotations: map[string]string{
util.CommandProcessOutput: "",
},
Use: "pkglist [OPTIONS]",
Short: "List of the packages found in tree.",
Args: cobra.NoArgs,
@ -95,9 +99,6 @@ func NewTreePkglistCommand() *cobra.Command {
deps, _ := cmd.Flags().GetBool("deps")
out, _ := cmd.Flags().GetString("output")
if out != "terminal" {
util.DefaultContext.Config.GetLogging().SetLogLevel("error")
}
var reciper tree.Builder
if buildtime {

View File

@ -255,7 +255,7 @@ func validatePackage(p pkg.Package, checkType string, opts *ValidateOpts, recipe
r.GetCategory(), r.GetName(), r.GetVersion(),
))
if util.DefaultContext.Config.GetGeneral().Debug {
if util.DefaultContext.Config.General.Debug {
for idx, pa := range solution {
fmt.Println(fmt.Sprintf("[%9s] %s/%s-%s: solution %d: %s",
checkType,
@ -426,7 +426,7 @@ func NewTreeValidateCommand() *cobra.Command {
Run: func(cmd *cobra.Command, args []string) {
var reciper tree.Builder
concurrency := util.DefaultContext.Config.GetGeneral().Concurrency
concurrency := util.DefaultContext.Config.General.Concurrency
withSolver, _ := cmd.Flags().GetBool("with-solver")
onlyRuntime, _ := cmd.Flags().GetBool("only-runtime")

View File

@ -17,7 +17,6 @@ package cmd
import (
helpers "github.com/mudler/luet/cmd/helpers"
"github.com/mudler/luet/cmd/util"
"github.com/mudler/luet/pkg/api/core/types"
installer "github.com/mudler/luet/pkg/installer"
pkg "github.com/mudler/luet/pkg/package"
"github.com/mudler/luet/pkg/solver"
@ -32,8 +31,7 @@ var uninstallCmd = &cobra.Command{
Long: `Uninstall packages`,
Aliases: []string{"rm", "un"},
PreRun: func(cmd *cobra.Command, args []string) {
util.BindSystemFlags(cmd)
util.BindSolverFlags(cmd)
viper.BindPFlag("nodeps", cmd.Flags().Lookup("nodeps"))
viper.BindPFlag("force", cmd.Flags().Lookup("force"))
viper.BindPFlag("yes", cmd.Flags().Lookup("yes"))
@ -57,21 +55,15 @@ var uninstallCmd = &cobra.Command{
yes := viper.GetBool("yes")
keepProtected, _ := cmd.Flags().GetBool("keep-protected-files")
util.SetSystemConfig(util.DefaultContext)
util.SetSolverConfig(util.DefaultContext)
util.DefaultContext.Config.ConfigProtectSkip = !keepProtected
util.DefaultContext.Config.GetSolverOptions().Implementation = solver.SingleCoreSimple
util.DefaultContext.Config.Solver.Implementation = solver.SingleCoreSimple
util.DefaultContext.Debug("Solver", util.DefaultContext.Config.GetSolverOptions().CompactString())
// Load config protect configs
util.DefaultContext.Config.LoadConfigProtect(util.DefaultContext)
util.DefaultContext.Debug("Solver", util.DefaultContext.Config.Solver.CompactString())
inst := installer.NewLuetInstaller(installer.LuetInstallerOptions{
Concurrency: util.DefaultContext.Config.GetGeneral().Concurrency,
SolverOptions: *util.DefaultContext.Config.GetSolverOptions(),
Concurrency: util.DefaultContext.Config.General.Concurrency,
SolverOptions: util.DefaultContext.Config.Solver,
NoDeps: nodeps,
Force: force,
FullUninstall: full,
@ -82,7 +74,7 @@ var uninstallCmd = &cobra.Command{
Context: util.DefaultContext,
})
system := &installer.System{Database: util.DefaultContext.Config.GetSystemDB(), Target: util.DefaultContext.Config.GetSystem().Rootfs}
system := &installer.System{Database: util.DefaultContext.Config.GetSystemDB(), Target: util.DefaultContext.Config.System.Rootfs}
if err := inst.Uninstall(system, toRemove...); err != nil {
util.DefaultContext.Fatal("Error: " + err.Error())
@ -92,14 +84,6 @@ var uninstallCmd = &cobra.Command{
func init() {
uninstallCmd.Flags().String("system-dbpath", "", "System db path")
uninstallCmd.Flags().String("system-target", "", "System rootpath")
uninstallCmd.Flags().String("system-engine", "", "System DB engine")
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-discount", 1.0, "Solver discount rate")
uninstallCmd.Flags().Int("solver-attempts", 9000, "Solver maximum attempts")
uninstallCmd.Flags().Bool("nodeps", false, "Don't consider package dependencies (harmful! overrides checkconflicts and full!)")
uninstallCmd.Flags().Bool("force", false, "Force uninstall")
uninstallCmd.Flags().Bool("full", false, "Attempts to remove as much packages as possible which aren't required (slow)")

View File

@ -16,7 +16,6 @@ package cmd
import (
"github.com/mudler/luet/cmd/util"
"github.com/mudler/luet/pkg/api/core/types"
installer "github.com/mudler/luet/pkg/installer"
"github.com/mudler/luet/pkg/solver"
@ -29,8 +28,7 @@ var upgradeCmd = &cobra.Command{
Short: "Upgrades the system",
Aliases: []string{"u"},
PreRun: func(cmd *cobra.Command, args []string) {
util.BindSystemFlags(cmd)
util.BindSolverFlags(cmd)
viper.BindPFlag("force", cmd.Flags().Lookup("force"))
viper.BindPFlag("yes", cmd.Flags().Lookup("yes"))
},
@ -48,19 +46,13 @@ var upgradeCmd = &cobra.Command{
yes := viper.GetBool("yes")
downloadOnly, _ := cmd.Flags().GetBool("download-only")
util.SetSystemConfig(util.DefaultContext)
opts := util.SetSolverConfig(util.DefaultContext)
util.DefaultContext.Config.Solver.Implementation = solver.SingleCoreSimple
util.DefaultContext.Config.GetSolverOptions().Implementation = solver.SingleCoreSimple
util.DefaultContext.Debug("Solver", opts.CompactString())
// Load config protect configs
util.DefaultContext.Config.LoadConfigProtect(util.DefaultContext)
util.DefaultContext.Debug("Solver", util.DefaultContext.GetConfig().Solver)
inst := installer.NewLuetInstaller(installer.LuetInstallerOptions{
Concurrency: util.DefaultContext.Config.GetGeneral().Concurrency,
SolverOptions: *util.DefaultContext.Config.GetSolverOptions(),
Concurrency: util.DefaultContext.Config.General.Concurrency,
SolverOptions: util.DefaultContext.Config.Solver,
Force: force,
FullUninstall: full,
NoDeps: nodeps,
@ -75,7 +67,7 @@ var upgradeCmd = &cobra.Command{
Context: util.DefaultContext,
})
system := &installer.System{Database: util.DefaultContext.Config.GetSystemDB(), Target: util.DefaultContext.Config.GetSystem().Rootfs}
system := &installer.System{Database: util.DefaultContext.Config.GetSystemDB(), Target: util.DefaultContext.Config.System.Rootfs}
if err := inst.Upgrade(system); err != nil {
util.DefaultContext.Fatal("Error: " + err.Error())
}
@ -83,14 +75,6 @@ var upgradeCmd = &cobra.Command{
}
func init() {
upgradeCmd.Flags().String("system-dbpath", "", "System db path")
upgradeCmd.Flags().String("system-target", "", "System rootpath")
upgradeCmd.Flags().String("system-engine", "", "System DB engine")
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-discount", 1.0, "Solver discount rate")
upgradeCmd.Flags().Int("solver-attempts", 9000, "Solver maximum attempts")
upgradeCmd.Flags().Bool("force", false, "Force upgrade by ignoring errors")
upgradeCmd.Flags().Bool("nodeps", false, "Don't consider package dependencies (harmful! overrides checkconflicts and full!)")
upgradeCmd.Flags().Bool("full", false, "Attempts to remove as much packages as possible which aren't required (slow)")

View File

@ -24,19 +24,19 @@ import (
"github.com/docker/docker/api/types"
"github.com/docker/go-units"
"github.com/mudler/luet/pkg/api/core/image"
luettypes "github.com/mudler/luet/pkg/api/core/types"
fileHelper "github.com/mudler/luet/pkg/helpers/file"
"github.com/pkg/errors"
"github.com/mudler/luet/cmd/util"
"github.com/mudler/luet/pkg/api/core/context"
"github.com/mudler/luet/pkg/helpers/docker"
"github.com/spf13/cobra"
)
func pack(ctx *luettypes.Context, p, dst, imageName, arch, OS string) error {
func pack(ctx *context.Context, p, dst, imageName, arch, OS string) error {
tempimage, err := ctx.Config.GetSystem().TempFile("tempimage")
tempimage, err := ctx.TempFile("tempimage")
if err != nil {
return errors.Wrap(err, "error met while creating tempdir for "+p)
}

View File

@ -16,7 +16,6 @@
package util
import (
"errors"
"os"
"path/filepath"
"strings"
@ -26,28 +25,14 @@ import (
"github.com/spf13/cobra"
"github.com/spf13/viper"
"github.com/mudler/luet/pkg/api/core/context"
"github.com/mudler/luet/pkg/api/core/types"
"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) {
viper.BindPFlag("system.database_path", cmd.Flags().Lookup("system-dbpath"))
viper.BindPFlag("system.rootfs", cmd.Flags().Lookup("system-target"))
viper.BindPFlag("system.database_engine", cmd.Flags().Lookup("system-engine"))
}
func BindSolverFlags(cmd *cobra.Command) {
viper.BindPFlag("solver.type", cmd.Flags().Lookup("solver-type"))
viper.BindPFlag("solver.discount", cmd.Flags().Lookup("solver-discount"))
viper.BindPFlag("solver.rate", cmd.Flags().Lookup("solver-rate"))
viper.BindPFlag("solver.max_attempts", cmd.Flags().Lookup("solver-attempts"))
}
func BindValuesFlags(cmd *cobra.Command) {
viper.BindPFlag("values", cmd.Flags().Lookup("values"))
}
@ -56,59 +41,14 @@ func ValuesFlags() []string {
return viper.GetStringSlice("values")
}
func SetSystemConfig(ctx *types.Context) {
dbpath := viper.GetString("system.database_path")
rootfs := viper.GetString("system.rootfs")
engine := viper.GetString("system.database_engine")
ctx.Config.System.DatabaseEngine = engine
ctx.Config.System.DatabasePath = dbpath
ctx.Config.System.SetRootFS(rootfs)
}
func SetSolverConfig(ctx *types.Context) (c *types.LuetSolverOptions) {
stype := viper.GetString("solver.type")
discount := viper.GetFloat64("solver.discount")
rate := viper.GetFloat64("solver.rate")
attempts := viper.GetInt("solver.max_attempts")
ctx.Config.GetSolverOptions().Type = stype
ctx.Config.GetSolverOptions().LearnRate = float32(rate)
ctx.Config.GetSolverOptions().Discount = float32(discount)
ctx.Config.GetSolverOptions().MaxAttempts = attempts
return &types.LuetSolverOptions{
Type: stype,
LearnRate: float32(rate),
Discount: float32(discount),
MaxAttempts: attempts,
}
}
func SetCliFinalizerEnvs(ctx *types.Context, finalizerEnvs []string) error {
if len(finalizerEnvs) > 0 {
for _, v := range finalizerEnvs {
idx := strings.Index(v, "=")
if idx < 0 {
return errors.New("Found invalid runtime finalizer environment: " + v)
}
ctx.Config.SetFinalizerEnv(v[0:idx], v[idx+1:])
}
}
return nil
}
// TemplateFolders returns the default folders which holds shared template between packages in a given tree path
func TemplateFolders(ctx *types.Context, fromRepo bool, treePaths []string) []string {
func TemplateFolders(ctx *context.Context, fromRepo bool, treePaths []string) []string {
templateFolders := []string{}
for _, t := range treePaths {
templateFolders = append(templateFolders, filepath.Join(t, "templates"))
}
if fromRepo {
for _, s := range installer.SystemRepositories(ctx.Config.SystemRepositories) {
for _, s := range installer.SystemRepositories(ctx.GetConfig().SystemRepositories) {
templateFolders = append(templateFolders, filepath.Join(s.TreePath, "templates"))
}
}
@ -126,7 +66,7 @@ func IntroScreen() {
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) {
func HandleLock(c types.Context) {
if os.Getenv("LUET_NOLOCK") != "true" {
if len(os.Args) > 1 {
for _, lockedCmd := range lockedCommands {
@ -146,7 +86,7 @@ func HandleLock(c *types.Context) {
}
}
func DisplayVersionBanner(c *types.Context, banner func(), version func() string, license []string) {
func DisplayVersionBanner(c *context.Context, banner func(), version func() string, license []string) {
display := false
if len(os.Args) > 1 {
for _, c := range bannerCommands {

View File

@ -16,6 +16,7 @@
package util
import (
"errors"
"fmt"
"os"
"os/user"
@ -23,8 +24,15 @@ import (
"runtime"
"strings"
"github.com/ipfs/go-log/v2"
extensions "github.com/mudler/cobra-extensions"
"github.com/mudler/luet/pkg/api/core/context"
gc "github.com/mudler/luet/pkg/api/core/garbagecollector"
"github.com/mudler/luet/pkg/api/core/logger"
"github.com/mudler/luet/pkg/api/core/types"
"github.com/mudler/luet/pkg/solver"
"github.com/pterm/pterm"
"go.uber.org/zap/zapcore"
helpers "github.com/mudler/luet/pkg/helpers"
fileHelper "github.com/mudler/luet/pkg/helpers/file"
@ -87,26 +95,117 @@ func initConfig() {
}
var DefaultContext *context.Context
// InitContext inits the context by parsing the configurations from viper
// this is meant to be run before each command to be able to parse any override from
// the CLI/ENV
func InitContext(ctx *types.Context) (err error) {
func InitContext(cmd *cobra.Command) (ctx *context.Context, err error) {
err = viper.Unmarshal(&ctx.Config)
c := &types.LuetConfig{}
err = viper.Unmarshal(c)
if err != nil {
return
}
// Converts user-defined config into paths
// and creates the required directory on the system if necessary
c.Init()
finalizerEnvs, _ := cmd.Flags().GetStringArray("finalizer-env")
setCliFinalizerEnvs(c, finalizerEnvs)
c.Solver.Options = solver.Options{Type: solver.SingleCoreSimple, Concurrency: c.General.Concurrency}
ctx = context.NewContext(
context.WithConfig(c),
context.WithGarbageCollector(gc.GarbageCollector(c.System.TmpDirBase)),
)
// 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 {
return
return ctx, initContext(cmd, ctx)
}
func setCliFinalizerEnvs(c *types.LuetConfig, finalizerEnvs []string) error {
if len(finalizerEnvs) > 0 {
for _, v := range finalizerEnvs {
idx := strings.Index(v, "=")
if idx < 0 {
return errors.New("Found invalid runtime finalizer environment: " + v)
}
c.SetFinalizerEnv(v[0:idx], v[idx+1:])
}
}
// no_spinner is not mapped in our configs
ctx.NoSpinner = viper.GetBool("no_spinner")
return nil
}
const (
CommandProcessOutput = "command.process.output"
)
func initContext(cmd *cobra.Command, c *context.Context) (err error) {
if logger.IsTerminal() {
if !c.Config.Logging.Color {
pterm.DisableColor()
}
} else {
pterm.DisableColor()
c.Debug("Not a terminal, colors disabled")
}
if c.Config.General.Quiet {
pterm.DisableColor()
pterm.DisableStyling()
}
level := c.Config.Logging.Level
if c.Config.General.Debug {
level = "debug"
}
if _, ok := cmd.Annotations[CommandProcessOutput]; ok {
// Note: create-repo output is different, so we annotate in the cmd of create-repo CommandNoProcess
// to avoid
out, _ := cmd.Flags().GetString("output")
if out != "terminal" {
level = zapcore.Level(log.LevelFatal).String()
}
}
// Init logging
opts := []logger.LoggerOptions{
logger.WithLevel(level),
}
if c.Config.Logging.NoSpinner {
opts = append(opts, logger.NoSpinner)
}
if c.Config.Logging.EnableLogFile && c.Config.Logging.Path != "" {
f := "console"
if c.Config.Logging.JsonFormat {
f = "json"
}
opts = append(opts, logger.WithFileLogging(c.Config.Logging.Path, f))
}
if c.Config.Logging.EnableEmoji {
opts = append(opts, logger.EnableEmoji())
}
l, err := logger.New(opts...)
c.Logger = l
c.Debug("System rootfs:", c.Config.System.Rootfs)
c.Debug("Colors", c.Config.Logging.Color)
c.Debug("Logging level", c.Config.Logging.Level)
c.Debug("Debug mode", c.Config.General.Debug)
return
}
@ -156,7 +255,7 @@ func setDefaults(viper *viper.Viper) {
// 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) {
func InitViper(RootCmd *cobra.Command) {
cobra.OnInitialize(initConfig)
pflags := RootCmd.PersistentFlags()
pflags.StringVar(&cfgFile, "config", "", "config file (default is $HOME/.luet.yaml)")
@ -165,29 +264,38 @@ func InitViper(ctx *types.Context, RootCmd *cobra.Command) {
pflags.Bool("fatal", false, "Enables Warnings to exit")
pflags.Bool("enable-logfile", false, "Enable log to file")
pflags.Bool("no-spinner", false, "Disable spinner.")
pflags.Bool("color", ctx.Config.GetLogging().Color, "Enable/Disable color.")
pflags.Bool("emoji", ctx.Config.GetLogging().EnableEmoji, "Enable/Disable emoji.")
pflags.Bool("skip-config-protect", ctx.Config.ConfigProtectSkip,
"Disable config protect analysis.")
pflags.StringP("logfile", "l", ctx.Config.GetLogging().Path,
"Logfile path. Empty value disable log to file.")
pflags.Bool("color", true, "Enable/Disable color.")
pflags.Bool("emoji", true, "Enable/Disable emoji.")
pflags.Bool("skip-config-protect", true, "Disable config protect analysis.")
pflags.StringP("logfile", "l", "", "Logfile path. Empty value disable log to file.")
pflags.StringSlice("plugin", []string{}, "A list of runtime plugins to load")
// os/user doesn't work in from scratch environments.
// Check if i can retrieve user informations.
_, err := user.Current()
if err != nil {
ctx.Warning("failed to retrieve user identity:", err.Error())
}
pflags.Bool("same-owner", ctx.Config.GetGeneral().SameOwner, "Maintain same owner on uncompress.")
pflags.String("system-dbpath", "", "System db path")
pflags.String("system-target", "", "System rootpath")
pflags.String("system-engine", "", "System DB engine")
pflags.String("solver-type", "", "Solver strategy ( Defaults none, available: "+types.AvailableResolvers+" )")
pflags.Float32("solver-rate", 0.7, "Solver learning rate")
pflags.Float32("solver-discount", 1.0, "Solver discount rate")
pflags.Int("solver-attempts", 9000, "Solver maximum attempts")
pflags.Bool("same-owner", true, "Maintain same owner on uncompress.")
pflags.Int("concurrency", runtime.NumCPU(), "Concurrency")
pflags.Int("http-timeout", ctx.Config.General.HTTPTimeout, "Default timeout for http(s) requests")
pflags.Int("http-timeout", 360, "Default timeout for http(s) requests")
viper.BindPFlag("system.database_path", pflags.Lookup("system-dbpath"))
viper.BindPFlag("system.rootfs", pflags.Lookup("system-target"))
viper.BindPFlag("system.database_engine", pflags.Lookup("system-engine"))
viper.BindPFlag("solver.type", pflags.Lookup("solver-type"))
viper.BindPFlag("solver.discount", pflags.Lookup("solver-discount"))
viper.BindPFlag("solver.rate", pflags.Lookup("solver-rate"))
viper.BindPFlag("solver.max_attempts", pflags.Lookup("solver-attempts"))
viper.BindPFlag("logging.color", pflags.Lookup("color"))
viper.BindPFlag("logging.enable_emoji", pflags.Lookup("emoji"))
viper.BindPFlag("logging.enable_logfile", pflags.Lookup("enable-logfile"))
viper.BindPFlag("logging.path", pflags.Lookup("logfile"))
viper.BindPFlag("logging.no_spinner", pflags.Lookup("no-spinner"))
viper.BindPFlag("general.concurrency", pflags.Lookup("concurrency"))
viper.BindPFlag("general.debug", pflags.Lookup("debug"))
viper.BindPFlag("general.quiet", pflags.Lookup("quiet"))

4
go.mod
View File

@ -30,12 +30,14 @@ require (
github.com/hashicorp/go-version v1.3.0
github.com/huandu/xstrings v1.3.2 // indirect
github.com/imdario/mergo v0.3.12
github.com/ipfs/go-log/v2 v2.4.0
github.com/jinzhu/copier v0.0.0-20180308034124-7e38e58719c3
github.com/klauspost/compress v1.13.0
github.com/klauspost/pgzip v1.2.5
github.com/knqyf263/go-deb-version v0.0.0-20190517075300-09fca494f03d
github.com/kyokomi/emoji v2.1.0+incompatible
github.com/marcsauter/single v0.0.0-20181104081128-f8bf46f26ec0
github.com/mattn/go-isatty v0.0.14
github.com/mitchellh/copystructure v1.2.0 // indirect
github.com/mitchellh/hashstructure/v2 v2.0.1
github.com/mitchellh/mapstructure v1.4.2 // indirect
@ -65,7 +67,7 @@ require (
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 // indirect
golang.org/x/mod v0.4.2
golang.org/x/oauth2 v0.0.0-20210810183815-faf39c7919d5 // indirect
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654 // indirect
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect
google.golang.org/genproto v0.0.0-20210811021853-ddbe55d93216 // indirect

7
go.sum
View File

@ -663,6 +663,8 @@ github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo=
github.com/ipfs/go-log/v2 v2.4.0 h1:iR/2o9PGWanVJrBgIH5Ff8mPGOwpqLaPIAFqSnsdlzk=
github.com/ipfs/go-log/v2 v2.4.0/go.mod h1:nPZnh7Cj7lwS3LpRU5Mwr2ol1c2gXIEXuF6aywqrtmo=
github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56/go.mod h1:ymszkNOg6tORTn+6F6j+Jc8TOr5osrynvN6ivFWZ2GA=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/jinzhu/copier v0.0.0-20180308034124-7e38e58719c3 h1:sHsPfNMAG70QAvKbddQ0uScZCHQoZsT5NykGRCeeeIs=
@ -747,6 +749,8 @@ github.com/marstr/guid v1.1.0/go.mod h1:74gB1z2wpxxInTG6yaqA7KrtM0NZ+RbrcqDvYHef
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/mattn/go-oci8 v0.0.7/go.mod h1:wjDx6Xm9q7dFtHJvIlrI99JytznLw5wQ4R+9mNXJwGI=
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
@ -1139,15 +1143,18 @@ go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqe
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4=
go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU=
go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4=
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM=
go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ=
go.uber.org/zap v1.17.0 h1:MTjgFu6ZLKvY6Pvaqk97GlxNBuMpV4Hy/3P6tRGlI2U=
go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo=
golang.org/x/crypto v0.0.0-20171113213409-9f005a07e0d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=

View File

@ -90,7 +90,7 @@ type Bus struct {
*pluggable.Manager
}
func (b *Bus) Initialize(ctx *types.Context, plugin ...string) {
func (b *Bus) Initialize(ctx types.Context, plugin ...string) {
b.Manager.Load(plugin...).Register()
for _, e := range b.Manager.Events {

View File

@ -18,7 +18,7 @@ package config_test
import (
config "github.com/mudler/luet/pkg/api/core/config"
"github.com/mudler/luet/pkg/api/core/types"
"github.com/mudler/luet/pkg/api/core/context"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
@ -29,7 +29,7 @@ var _ = Describe("Config", func() {
Context("Test config protect", func() {
It("Protect1", func() {
ctx := types.NewContext()
ctx := context.NewContext()
files := []string{
"etc/foo/my.conf",
"usr/bin/foo",
@ -59,7 +59,7 @@ var _ = Describe("Config", func() {
})
It("Protect2", func() {
ctx := types.NewContext()
ctx := context.NewContext()
files := []string{
"etc/foo/my.conf",
@ -86,7 +86,7 @@ var _ = Describe("Config", func() {
})
It("Protect3: Annotation dir without initial slash", func() {
ctx := types.NewContext()
ctx := context.NewContext()
files := []string{
"etc/foo/my.conf",

View File

@ -0,0 +1,28 @@
// 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 context_test
import (
"testing"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
func TestContext(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "Context Suite")
}

View File

@ -0,0 +1,159 @@
// 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 context
import (
"context"
"os"
"path/filepath"
fileHelper "github.com/mudler/luet/pkg/helpers/file"
gc "github.com/mudler/luet/pkg/api/core/garbagecollector"
"github.com/mudler/luet/pkg/api/core/logger"
"github.com/mudler/luet/pkg/api/core/types"
"github.com/pkg/errors"
)
type Context struct {
*logger.Logger
context.Context
types.GarbageCollector
Config *types.LuetConfig
NoSpinner bool
annotations map[string]interface{}
}
// SetAnnotation sets generic annotations to hold in a context
func (c *Context) SetAnnotation(s string, i interface{}) {
c.annotations[s] = i
}
// GetAnnotation gets generic annotations to hold in a context
func (c *Context) GetAnnotation(s string) interface{} {
return c.annotations[s]
}
type ContextOption func(c *Context) error
// WithLogger sets the logger
func WithLogger(l *logger.Logger) ContextOption {
return func(c *Context) error {
c.Logger = l
return nil
}
}
// WithConfig sets the luet config
func WithConfig(cc *types.LuetConfig) ContextOption {
return func(c *Context) error {
c.Config = cc
return nil
}
}
// NOTE: GC needs to be instantiated when a new context is created from system TmpDirBase
// WithGarbageCollector sets the Garbage collector for the given context
func WithGarbageCollector(l types.GarbageCollector) ContextOption {
return func(c *Context) error {
if !filepath.IsAbs(l.String()) {
abs, err := fileHelper.Rel2Abs(l.String())
if err != nil {
return errors.Wrap(err, "while converting relative path to absolute path")
}
l = gc.GarbageCollector(abs)
}
c.GarbageCollector = l
return nil
}
}
// NewContext returns a new context.
// It accepts a Garbage collector, a config and a logger as an option
func NewContext(opts ...ContextOption) *Context {
l, _ := logger.New()
d := &Context{
annotations: make(map[string]interface{}),
Logger: l,
GarbageCollector: gc.GarbageCollector(filepath.Join(os.TempDir(), "tmpluet")),
Config: &types.LuetConfig{
ConfigFromHost: true,
Logging: types.LuetLoggingConfig{},
General: types.LuetGeneralConfig{},
System: types.LuetSystemConfig{
DatabasePath: filepath.Join("var", "db"),
PkgsCachePath: filepath.Join("var", "db", "packages"),
},
Solver: types.LuetSolverOptions{},
},
}
for _, o := range opts {
o(d)
}
return d
}
// WithLoggingContext returns a copy of the context with a contextualized logger
func (c *Context) WithLoggingContext(name string) types.Context {
configCopy := *c.Config
configCopy.System = c.Config.System
configCopy.General = c.Config.General
configCopy.Logging = c.Config.Logging
ctx := *c
ctxCopy := &ctx
ctxCopy.Config = &configCopy
ctxCopy.annotations = ctx.annotations
ctxCopy.Logger, _ = c.Logger.Copy(logger.WithContext(name))
return ctxCopy
}
// Copy returns a context copy with a reset logging context
func (c *Context) Copy() types.Context {
return c.WithLoggingContext("")
}
func (c *Context) Warning(mess ...interface{}) {
c.Logger.Warn(mess...)
if c.Config.General.FatalWarns {
os.Exit(2)
}
}
func (c *Context) Warn(mess ...interface{}) {
c.Warning(mess...)
}
func (c *Context) Warnf(t string, mess ...interface{}) {
c.Logger.Warnf(t, mess...)
if c.Config.General.FatalWarns {
os.Exit(2)
}
}
func (c *Context) Warningf(t string, mess ...interface{}) {
c.Warnf(t, mess...)
}
func (c *Context) GetConfig() types.LuetConfig {
return *c.Config
}

View File

@ -0,0 +1,59 @@
// 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 gc
import (
"io/ioutil"
"os"
)
type GarbageCollector string
func (c GarbageCollector) String() string {
return string(c)
}
func (c GarbageCollector) init() error {
if _, err := os.Stat(string(c)); err != nil {
if os.IsNotExist(err) {
err = os.MkdirAll(string(c), os.ModePerm)
if err != nil {
return err
}
}
}
return nil
}
func (c GarbageCollector) Clean() error {
return os.RemoveAll(string(c))
}
func (c GarbageCollector) TempDir(pattern string) (string, error) {
err := c.init()
if err != nil {
return "", err
}
return ioutil.TempDir(string(c), pattern)
}
func (c GarbageCollector) TempFile(s string) (*os.File, error) {
err := c.init()
if err != nil {
return nil, err
}
return ioutil.TempFile(string(c), s)
}

View File

@ -18,8 +18,8 @@ package image_test
import (
"path/filepath"
"github.com/mudler/luet/pkg/api/core/context"
. "github.com/mudler/luet/pkg/api/core/image"
"github.com/mudler/luet/pkg/api/core/types"
"github.com/mudler/luet/pkg/helpers/file"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
@ -27,16 +27,16 @@ import (
var _ = Describe("Cache", func() {
ctx := types.NewContext()
ctx := context.NewContext()
Context("used as k/v store", func() {
cache := &Cache{}
var dir string
BeforeEach(func() {
ctx = types.NewContext()
ctx = context.NewContext()
var err error
dir, err = ctx.Config.System.TempDir("foo")
dir, err = ctx.TempDir("foo")
Expect(err).ToNot(HaveOccurred())
cache = NewCache(dir, 10*1024*1024, 1) // 10MB Cache when upgrading to files. Max volatile memory of 1 row.
})

View File

@ -20,8 +20,8 @@ import (
"path/filepath"
"runtime"
"github.com/mudler/luet/pkg/api/core/context"
. "github.com/mudler/luet/pkg/api/core/image"
"github.com/mudler/luet/pkg/api/core/types"
"github.com/mudler/luet/pkg/api/core/types/artifact"
"github.com/mudler/luet/pkg/compiler/backend"
"github.com/mudler/luet/pkg/helpers/file"
@ -32,12 +32,12 @@ import (
var _ = Describe("Create", func() {
Context("Creates an OCI image from a standard tar", func() {
It("creates an image which is loadable", func() {
ctx := types.NewContext()
ctx := context.NewContext()
dst, err := ctx.Config.System.TempFile("dst")
dst, err := ctx.TempFile("dst")
Expect(err).ToNot(HaveOccurred())
defer os.RemoveAll(dst.Name())
srcTar, err := ctx.Config.System.TempFile("srcTar")
srcTar, err := ctx.TempFile("srcTar")
Expect(err).ToNot(HaveOccurred())
defer os.RemoveAll(srcTar.Name())

View File

@ -23,8 +23,8 @@ import (
"github.com/google/go-containerregistry/pkg/name"
v1 "github.com/google/go-containerregistry/pkg/v1"
daemon "github.com/google/go-containerregistry/pkg/v1/daemon"
"github.com/mudler/luet/pkg/api/core/context"
. "github.com/mudler/luet/pkg/api/core/image"
"github.com/mudler/luet/pkg/api/core/types"
"github.com/mudler/luet/pkg/helpers/file"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
@ -47,7 +47,7 @@ var _ = Describe("Delta", func() {
})
Context("ExtractDeltaFiles", func() {
ctx := types.NewContext()
ctx := context.NewContext()
var tmpfile *os.File
var ref, ref2 name.Reference
var img, img2 v1.Image
@ -59,7 +59,7 @@ var _ = Describe("Delta", func() {
img2, _ = daemon.Image(ref2)
BeforeEach(func() {
ctx = types.NewContext()
ctx = context.NewContext()
tmpfile, err = ioutil.TempFile("", "delta")
Expect(err).ToNot(HaveOccurred())

View File

@ -35,7 +35,7 @@ import (
// considering the added files only, and applies a filter on them based on the regexes
// in the lists.
func ExtractDeltaAdditionsFiles(
ctx *types.Context,
ctx types.Context,
srcimg v1.Image,
includes []string, excludes []string,
) (func(h *tar.Header) (bool, error), error) {
@ -43,7 +43,7 @@ func ExtractDeltaAdditionsFiles(
includeRegexp := compileRegexes(includes)
excludeRegexp := compileRegexes(excludes)
srcfilesd, err := ctx.Config.System.TempDir("srcfiles")
srcfilesd, err := ctx.TempDir("srcfiles")
if err != nil {
return nil, err
}
@ -128,7 +128,7 @@ func ExtractDeltaAdditionsFiles(
// It then filters files by an include and exclude list.
// The list can be regexes
func ExtractFiles(
ctx *types.Context,
ctx types.Context,
prefixPath string,
includes []string, excludes []string,
) func(h *tar.Header) (bool, error) {
@ -193,7 +193,7 @@ func ExtractFiles(
// ExtractReader perform the extracting action over the io.ReadCloser
// it extracts the files over output. Accepts a filter as an option
// and additional containerd Options
func ExtractReader(ctx *types.Context, reader io.ReadCloser, output string, filter func(h *tar.Header) (bool, error), opts ...containerdarchive.ApplyOpt) (int64, string, error) {
func ExtractReader(ctx types.Context, reader io.ReadCloser, output string, filter func(h *tar.Header) (bool, error), opts ...containerdarchive.ApplyOpt) (int64, string, error) {
defer reader.Close()
// If no filter is specified, grab all.
@ -213,8 +213,8 @@ func ExtractReader(ctx *types.Context, reader io.ReadCloser, output string, filt
}
// Extract is just syntax sugar around ExtractReader. It extracts an image into a dir
func Extract(ctx *types.Context, img v1.Image, filter func(h *tar.Header) (bool, error), opts ...containerdarchive.ApplyOpt) (int64, string, error) {
tmpdiffs, err := ctx.Config.GetSystem().TempDir("extraction")
func Extract(ctx types.Context, img v1.Image, filter func(h *tar.Header) (bool, error), opts ...containerdarchive.ApplyOpt) (int64, string, error) {
tmpdiffs, err := ctx.TempDir("extraction")
if err != nil {
return 0, "", errors.Wrap(err, "Error met while creating tempdir for rootfs")
}
@ -222,6 +222,6 @@ func Extract(ctx *types.Context, img v1.Image, filter func(h *tar.Header) (bool,
}
// ExtractTo is just syntax sugar around ExtractReader
func ExtractTo(ctx *types.Context, img v1.Image, output string, filter func(h *tar.Header) (bool, error), opts ...containerdarchive.ApplyOpt) (int64, string, error) {
func ExtractTo(ctx types.Context, img v1.Image, output string, filter func(h *tar.Header) (bool, error), opts ...containerdarchive.ApplyOpt) (int64, string, error) {
return ExtractReader(ctx, mutate.Extract(img), output, filter, opts...)
}

View File

@ -23,8 +23,8 @@ import (
"github.com/google/go-containerregistry/pkg/name"
v1 "github.com/google/go-containerregistry/pkg/v1"
daemon "github.com/google/go-containerregistry/pkg/v1/daemon"
"github.com/mudler/luet/pkg/api/core/context"
. "github.com/mudler/luet/pkg/api/core/image"
"github.com/mudler/luet/pkg/api/core/types"
"github.com/mudler/luet/pkg/helpers/file"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
@ -34,14 +34,14 @@ var _ = Describe("Extract", func() {
Context("extract files from images", func() {
Context("ExtractFiles", func() {
ctx := types.NewContext()
ctx := context.NewContext()
var tmpfile *os.File
var ref name.Reference
var img v1.Image
var err error
BeforeEach(func() {
ctx = types.NewContext()
ctx = context.NewContext()
tmpfile, err = ioutil.TempFile("", "extract")
Expect(err).ToNot(HaveOccurred())

View File

@ -18,7 +18,7 @@ package image_test
import (
"testing"
"github.com/mudler/luet/pkg/api/core/types"
"github.com/mudler/luet/pkg/api/core/context"
"github.com/mudler/luet/pkg/compiler/backend"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
@ -26,7 +26,7 @@ import (
func TestMutator(t *testing.T) {
RegisterFailHandler(Fail)
b := backend.NewSimpleDockerBackend(types.NewContext())
b := backend.NewSimpleDockerBackend(context.NewContext())
b.DownloadImage(backend.Options{ImageName: "alpine"})
b.DownloadImage(backend.Options{ImageName: "golang:alpine"})

View File

@ -0,0 +1,28 @@
// 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 logger_test
import (
"testing"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
func TestAPITypes(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "Types Suite")
}

View File

@ -0,0 +1,367 @@
// 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 logger
import (
"fmt"
"os"
"path"
"regexp"
"runtime"
"strings"
"sync"
log "github.com/ipfs/go-log/v2"
"github.com/kyokomi/emoji"
"github.com/pterm/pterm"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
)
// Logger is the default logger
type Logger struct {
level log.LogLevel
emoji bool
logToFile bool
noSpinner bool
fileLogger *zap.Logger
context string
spinnerLock sync.Mutex
s *pterm.SpinnerPrinter
}
// LogLevel represents a log severity level. Use the package variables as an
// enum.
type LogLevel zapcore.Level
type LoggerOptions func(*Logger) error
var NoSpinner LoggerOptions = func(l *Logger) error {
l.noSpinner = true
return nil
}
func WithLevel(level string) LoggerOptions {
return func(l *Logger) error {
lvl, _ := log.LevelFromString(level) // Defaults to Info
l.level = lvl
if l.level == log.LevelDebug {
pterm.EnableDebugMessages()
}
return nil
}
}
func WithContext(c string) LoggerOptions {
return func(l *Logger) error {
l.context = c
return nil
}
}
func WithFileLogging(p, encoding string) LoggerOptions {
return func(l *Logger) error {
if encoding == "" {
encoding = "console"
}
l.logToFile = true
var err error
cfg := zap.NewProductionConfig()
cfg.OutputPaths = []string{p}
cfg.Level = zap.NewAtomicLevelAt(zapcore.Level(l.level))
cfg.ErrorOutputPaths = []string{}
cfg.Encoding = encoding
cfg.DisableCaller = true
cfg.DisableStacktrace = true
cfg.EncoderConfig.TimeKey = "time"
cfg.EncoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder
l.fileLogger, err = cfg.Build()
return err
}
}
var EnableEmoji = func() LoggerOptions {
return func(l *Logger) error {
l.emoji = true
return nil
}
}
func New(opts ...LoggerOptions) (*Logger, error) {
l := &Logger{
level: log.LevelDebug,
s: pterm.DefaultSpinner.WithShowTimer(false).WithRemoveWhenDone(true),
}
for _, o := range opts {
if err := o(l); err != nil {
return nil, err
}
}
return l, nil
}
func (l *Logger) Copy(opts ...LoggerOptions) (*Logger, error) {
c := *l
copy := &c
for _, o := range opts {
if err := o(copy); err != nil {
return nil, err
}
}
return copy, nil
}
func joinMsg(args ...interface{}) (message string) {
for _, m := range args {
message += " " + fmt.Sprintf("%v", m)
}
return
}
func (l *Logger) enabled(lvl log.LogLevel) bool {
return lvl >= l.level
}
var emojiStrip = regexp.MustCompile(`[:][\w]+[:]`)
func (l *Logger) transform(args ...interface{}) (sanitized []interface{}) {
for _, a := range args {
var aString string
// Strip emoji if needed
if l.emoji {
aString = emoji.Sprint(a)
} else {
aString = emojiStrip.ReplaceAllString(joinMsg(a), "")
}
sanitized = append(sanitized, aString)
}
if l.context != "" {
sanitized = append([]interface{}{fmt.Sprintf("(%s)", l.context)}, sanitized...)
}
return
}
func prefixCodeLine(args ...interface{}) []interface{} {
pc, file, line, ok := runtime.Caller(3)
if ok {
args = append([]interface{}{fmt.Sprintf("(%s:#%d:%v)",
path.Base(file), line, runtime.FuncForPC(pc).Name())}, args...)
}
return args
}
func (l *Logger) send(ll log.LogLevel, f string, args ...interface{}) {
if !l.enabled(ll) {
return
}
sanitizedArgs := joinMsg(l.transform(args...)...)
sanitizedF := joinMsg(l.transform(f)...)
formatDefined := f != ""
switch {
case log.LevelDebug == ll && !formatDefined:
pterm.Debug.Println(prefixCodeLine(sanitizedArgs)...)
if l.logToFile {
l.fileLogger.Debug(joinMsg(prefixCodeLine(sanitizedArgs)...))
}
case log.LevelDebug == ll && formatDefined:
pterm.Debug.Printfln(sanitizedF, prefixCodeLine(args...)...)
if l.logToFile {
l.fileLogger.Sugar().Debugf(sanitizedF, prefixCodeLine(args...)...)
}
case log.LevelError == ll && !formatDefined:
pterm.Error.Println(pterm.LightRed(sanitizedArgs))
if l.logToFile {
l.fileLogger.Error(sanitizedArgs)
}
case log.LevelError == ll && formatDefined:
pterm.Error.Printfln(pterm.LightRed(sanitizedF), args...)
if l.logToFile {
l.fileLogger.Sugar().Errorf(sanitizedF, args...)
}
case log.LevelFatal == ll && !formatDefined:
pterm.Error.Println(sanitizedArgs)
if l.logToFile {
l.fileLogger.Error(sanitizedArgs)
}
case log.LevelFatal == ll && formatDefined:
pterm.Error.Printfln(sanitizedF, args...)
if l.logToFile {
l.fileLogger.Sugar().Errorf(sanitizedF, args...)
}
//INFO
case log.LevelInfo == ll && !formatDefined:
pterm.Info.Println(sanitizedArgs)
if l.logToFile {
l.fileLogger.Info(sanitizedArgs)
}
case log.LevelInfo == ll && formatDefined:
pterm.Info.Printfln(sanitizedF, args...)
if l.logToFile {
l.fileLogger.Sugar().Infof(sanitizedF, args...)
}
//WARN
case log.LevelWarn == ll && !formatDefined:
pterm.Warning.Println(sanitizedArgs)
if l.logToFile {
l.fileLogger.Warn(sanitizedArgs)
}
case log.LevelWarn == ll && formatDefined:
pterm.Warning.Printfln(sanitizedF, args...)
if l.logToFile {
l.fileLogger.Sugar().Warnf(sanitizedF, args...)
}
}
}
func (l *Logger) Debug(args ...interface{}) {
l.send(log.LevelDebug, "", args...)
}
func (l *Logger) Error(args ...interface{}) {
l.send(log.LevelError, "", args...)
}
func (l *Logger) Trace(args ...interface{}) {
l.send(log.LevelDebug, "", args...)
}
func (l *Logger) Tracef(t string, args ...interface{}) {
l.send(log.LevelDebug, t, args...)
}
func (l *Logger) Fatal(args ...interface{}) {
l.send(log.LevelFatal, "", args...)
os.Exit(1)
}
func (l *Logger) Info(args ...interface{}) {
l.send(log.LevelInfo, "", args...)
}
func (l *Logger) Success(args ...interface{}) {
l.Info(append([]interface{}{"SUCCESS"}, args...)...)
}
func (l *Logger) Panic(args ...interface{}) {
l.Fatal(args...)
}
func (l *Logger) Warn(args ...interface{}) {
l.send(log.LevelWarn, "", args...)
}
func (l *Logger) Warning(args ...interface{}) {
l.Warn(args...)
}
func (l *Logger) Debugf(f string, args ...interface{}) {
l.send(log.LevelDebug, f, args...)
}
func (l *Logger) Errorf(f string, args ...interface{}) {
l.send(log.LevelError, f, args...)
}
func (l *Logger) Fatalf(f string, args ...interface{}) {
l.send(log.LevelFatal, f, args...)
}
func (l *Logger) Infof(f string, args ...interface{}) {
l.send(log.LevelInfo, f, args...)
}
func (l *Logger) Panicf(f string, args ...interface{}) {
l.Fatalf(joinMsg(f), args...)
}
func (l *Logger) Warnf(f string, args ...interface{}) {
l.send(log.LevelWarn, f, args...)
}
func (l *Logger) Warningf(f string, args ...interface{}) {
l.Warnf(f, args...)
}
func (l *Logger) Ask() bool {
var input string
l.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
}
// Spinner starts the spinner
func (l *Logger) Spinner() {
if !IsTerminal() || l.noSpinner {
return
}
l.spinnerLock.Lock()
defer l.spinnerLock.Unlock()
if l.s != nil && !l.s.IsActive {
l.s, _ = l.s.Start()
}
}
func (l *Logger) Screen(text string) {
pterm.DefaultHeader.WithBackgroundStyle(pterm.NewStyle(pterm.BgLightBlue)).WithMargin(2).Println(text)
}
func (l *Logger) SpinnerText(suffix, prefix string) {
if !IsTerminal() || l.noSpinner {
return
}
l.spinnerLock.Lock()
defer l.spinnerLock.Unlock()
if l.level == log.LevelDebug {
fmt.Printf("%s %s\n",
suffix, prefix,
)
} else {
l.s.UpdateText(suffix + prefix)
}
}
func (l *Logger) SpinnerStop() {
if !IsTerminal() || l.noSpinner {
return
}
l.spinnerLock.Lock()
defer l.spinnerLock.Unlock()
if l.s != nil {
l.s.Success()
}
}

View File

@ -13,7 +13,7 @@
// 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
package logger_test
import (
"io"
@ -21,7 +21,8 @@ import (
"os"
"github.com/gookit/color"
types "github.com/mudler/luet/pkg/api/core/types"
"github.com/mudler/luet/pkg/api/core/logger"
. "github.com/mudler/luet/pkg/api/core/logger"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
@ -44,30 +45,11 @@ func captureStdout(f func(w io.Writer)) string {
}
var _ = Describe("Context and logging", func() {
ctx := types.NewContext()
BeforeEach(func() {
ctx = types.NewContext()
})
Context("LogLevel", func() {
It("converts it correctly to number and zaplog", func() {
Expect(types.ErrorLevel.ToNumber()).To(Equal(0))
Expect(types.InfoLevel.ToNumber()).To(Equal(2))
Expect(types.WarningLevel.ToNumber()).To(Equal(1))
Expect(types.LogLevel("foo").ToNumber()).To(Equal(3))
Expect(types.WarningLevel.ZapLevel().String()).To(Equal("warn"))
Expect(types.InfoLevel.ZapLevel().String()).To(Equal("info"))
Expect(types.ErrorLevel.ZapLevel().String()).To(Equal("error"))
Expect(types.FatalLevel.ZapLevel().String()).To(Equal("fatal"))
Expect(types.LogLevel("foo").ZapLevel().String()).To(Equal("debug"))
})
})
Context("Context", func() {
It("detect if is a terminal", func() {
Expect(captureStdout(func(w io.Writer) {
_, _, err := ctx.GetTerminalSize()
_, _, err := GetTerminalSize()
Expect(err).To(HaveOccurred())
Expect(err.Error()).To(Equal("size not detectable"))
os.Stdout.Write([]byte(err.Error()))
@ -75,47 +57,71 @@ var _ = Describe("Context and logging", func() {
})
It("respects loglevel", func() {
ctx.Config.GetGeneral().Debug = false
l, err := New(WithLevel("info"))
Expect(err).ToNot(HaveOccurred())
Expect(captureStdout(func(w io.Writer) {
ctx.Debug("")
l.Debug("")
})).To(Equal(""))
ctx.Config.GetGeneral().Debug = true
l, err = New(WithLevel("debug"))
Expect(err).ToNot(HaveOccurred())
Expect(captureStdout(func(w io.Writer) {
ctx.Debug("foo")
l.Debug("foo")
})).To(ContainSubstring("foo"))
})
It("logs with context", func() {
l, err := New(WithLevel("debug"), WithContext("foo"))
Expect(err).ToNot(HaveOccurred())
Expect(captureStdout(func(w io.Writer) {
l.Debug("bar")
})).To(ContainSubstring("(foo) bar"))
})
It("returns copies with logged context", func() {
l, err := New(WithLevel("debug"))
l, _ = l.Copy(logger.WithContext("bazzz"))
Expect(err).ToNot(HaveOccurred())
Expect(captureStdout(func(w io.Writer) {
l.Debug("bar")
})).To(ContainSubstring("(bazzz) bar"))
})
It("logs to file", func() {
ctx.NoColor()
t, err := ioutil.TempFile("", "tree")
Expect(err).ToNot(HaveOccurred())
defer os.RemoveAll(t.Name()) // clean up
ctx.Config.GetLogging().EnableLogFile = true
ctx.Config.GetLogging().Path = t.Name()
ctx.Init()
l, err := New(WithLevel("debug"), WithFileLogging(t.Name(), ""))
Expect(err).ToNot(HaveOccurred())
// ctx.Init()
Expect(captureStdout(func(w io.Writer) {
ctx.Info("foot")
l.Info("foot")
})).To(And(ContainSubstring("INFO"), ContainSubstring("foot")))
Expect(captureStdout(func(w io.Writer) {
ctx.Success("test")
l.Success("test")
})).To(And(ContainSubstring("SUCCESS"), ContainSubstring("test")))
Expect(captureStdout(func(w io.Writer) {
ctx.Error("foobar")
l.Error("foobar")
})).To(And(ContainSubstring("ERROR"), ContainSubstring("foobar")))
Expect(captureStdout(func(w io.Writer) {
ctx.Warning("foowarn")
l.Warning("foowarn")
})).To(And(ContainSubstring("WARNING"), ContainSubstring("foowarn")))
l, err := ioutil.ReadFile(t.Name())
ll, err := ioutil.ReadFile(t.Name())
Expect(err).ToNot(HaveOccurred())
logs := string(l)
logs := string(ll)
Expect(logs).To(ContainSubstring("foot"))
Expect(logs).To(ContainSubstring("test"))
Expect(logs).To(ContainSubstring("foowarn"))

View File

@ -0,0 +1,43 @@
// 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 logger
import (
"errors"
"os"
"github.com/mattn/go-isatty"
"golang.org/x/term"
)
func IsTerminal() bool {
return isatty.IsTerminal(os.Stdout.Fd())
}
// GetTerminalSize returns the width and the height of the active terminal.
func GetTerminalSize() (width, height int, err error) {
w, h, err := term.GetSize(int(os.Stdout.Fd()))
if w <= 0 {
w = 0
}
if h <= 0 {
h = 0
}
if err != nil {
err = errors.New("size not detectable")
}
return w, h, err
}

View File

@ -41,7 +41,7 @@ import (
bus "github.com/mudler/luet/pkg/api/core/bus"
config "github.com/mudler/luet/pkg/api/core/config"
"github.com/mudler/luet/pkg/api/core/image"
types "github.com/mudler/luet/pkg/api/core/types"
"github.com/mudler/luet/pkg/api/core/types"
backend "github.com/mudler/luet/pkg/compiler/backend"
compression "github.com/mudler/luet/pkg/compiler/types/compression"
compilerspec "github.com/mudler/luet/pkg/compiler/types/spec"
@ -70,7 +70,7 @@ type PackageArtifact struct {
Runtime *pkg.DefaultPackage `json:"runtime,omitempty"`
}
func ImageToArtifact(ctx *types.Context, img v1.Image, t compression.Implementation, output string, filter func(h *tar.Header) (bool, error)) (*PackageArtifact, error) {
func ImageToArtifact(ctx types.Context, img v1.Image, t compression.Implementation, output string, filter func(h *tar.Header) (bool, error)) (*PackageArtifact, error) {
_, tmpdiffs, err := image.Extract(ctx, img, filter)
if err != nil {
return nil, errors.Wrap(err, "Error met while creating tempdir for rootfs")
@ -176,12 +176,12 @@ func (a *PackageArtifact) GetFileName() string {
}
// CreateArtifactForFile creates a new artifact from the given file
func CreateArtifactForFile(ctx *types.Context, 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) {
return nil, errors.Wrap(err, "artifact path doesn't exist")
}
fileName := path.Base(s)
archive, err := ctx.Config.GetSystem().TempDir("archive")
archive, err := ctx.TempDir("archive")
if err != nil {
return nil, errors.Wrap(err, "error met while creating tempdir for "+s)
}
@ -191,7 +191,7 @@ func CreateArtifactForFile(ctx *types.Context, s string, opts ...func(*PackageAr
return nil, errors.Wrapf(err, "error while copying %s to %s", s, dst)
}
artifact, err := ctx.Config.GetSystem().TempDir("artifact")
artifact, err := ctx.TempDir("artifact")
if err != nil {
return nil, errors.Wrap(err, "error met while creating tempdir for "+s)
}
@ -210,9 +210,9 @@ type ImageBuilder interface {
}
// GenerateFinalImage takes an artifact and builds a Docker image with its content
func (a *PackageArtifact) GenerateFinalImage(ctx *types.Context, imageName string, b ImageBuilder, keepPerms bool) error {
func (a *PackageArtifact) GenerateFinalImage(ctx types.Context, imageName string, b ImageBuilder, keepPerms bool) error {
tempimage, err := ctx.Config.GetSystem().TempFile("tempimage")
tempimage, err := ctx.TempFile("tempimage")
if err != nil {
return errors.Wrap(err, "error met while creating tempdir for "+a.Path)
}
@ -428,7 +428,7 @@ func replaceFileTarWrapper(dst string, inputTarStream io.ReadCloser, mods []stri
return pipeReader
}
func tarModifierWrapperFunc(ctx *types.Context) func(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) {
return 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.
var destPath string
@ -495,10 +495,10 @@ func tarModifierWrapperFunc(ctx *types.Context) func(dst, path string, header *t
}
}
func (a *PackageArtifact) GetProtectFiles(ctx *types.Context) (res []string) {
func (a *PackageArtifact) GetProtectFiles(ctx types.Context) (res []string) {
annotationDir := ""
if !ctx.Config.ConfigProtectSkip {
if !ctx.GetConfig().ConfigProtectSkip {
// a.CompileSpec could be nil when artifact.Unpack is used for tree tarball
if a.CompileSpec != nil &&
@ -511,7 +511,7 @@ func (a *PackageArtifact) GetProtectFiles(ctx *types.Context) (res []string) {
// TODO: check if skip this if we have a.CompileSpec nil
cp := config.NewConfigProtect(annotationDir)
cp.Map(a.Files, ctx.Config.GetConfigProtectConfFiles())
cp.Map(a.Files, ctx.GetConfig().ConfigProtectConfFiles)
// NOTE: for unpack we need files path without initial /
res = cp.GetProtectFiles(false)
@ -521,7 +521,7 @@ func (a *PackageArtifact) GetProtectFiles(ctx *types.Context) (res []string) {
}
// Unpack Untar and decompress (TODO) to the given path
func (a *PackageArtifact) Unpack(ctx *types.Context, dst string, keepPerms bool) error {
func (a *PackageArtifact) Unpack(ctx types.Context, dst string, keepPerms bool) error {
if !strings.HasPrefix(dst, string(os.PathSeparator)) {
return errors.New("destination must be an absolute path")

View File

@ -20,10 +20,9 @@ import (
"os"
"path/filepath"
"github.com/mudler/luet/pkg/api/core/context"
"github.com/mudler/luet/pkg/api/core/image"
"github.com/mudler/luet/pkg/api/core/types"
. "github.com/mudler/luet/pkg/api/core/types/artifact"
. "github.com/mudler/luet/pkg/compiler/backend"
backend "github.com/mudler/luet/pkg/compiler/backend"
compression "github.com/mudler/luet/pkg/compiler/types/compression"
"github.com/mudler/luet/pkg/compiler/types/options"
@ -39,7 +38,7 @@ import (
var _ = Describe("Artifact", func() {
Context("Simple package build definition", func() {
ctx := types.NewContext()
ctx := context.NewContext()
It("Generates a verified delta", func() {
generalRecipe := tree.NewGeneralRecipe(pkg.NewInMemoryDatabase(false))
@ -49,7 +48,7 @@ var _ = Describe("Artifact", func() {
Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(1))
cc := NewLuetCompiler(nil, generalRecipe.GetDatabase(), options.WithContext(types.NewContext()))
cc := NewLuetCompiler(nil, generalRecipe.GetDatabase(), options.WithContext(context.NewContext()))
lspec, err := cc.FromPackage(&pkg.DefaultPackage{Name: "enman", Category: "app-admin", Version: "1.4.0"})
Expect(err).ToNot(HaveOccurred())
@ -83,7 +82,7 @@ WORKDIR /luetbuild
ENV PACKAGE_NAME=enman
ENV PACKAGE_VERSION=1.4.0
ENV PACKAGE_CATEGORY=app-admin`))
b := NewSimpleDockerBackend(ctx)
b := backend.NewSimpleDockerBackend(ctx)
opts := backend.Options{
ImageName: "luet/base",
SourcePath: tmpdir,
@ -120,7 +119,7 @@ RUN echo bar > /test2`))
})
It("Generates packages images", func() {
b := NewSimpleDockerBackend(ctx)
b := backend.NewSimpleDockerBackend(ctx)
imageprefix := "foo/"
testString := []byte(`funky test data`)
@ -177,7 +176,7 @@ RUN echo bar > /test2`))
})
It("Generates empty packages images", func() {
b := NewSimpleDockerBackend(ctx)
b := backend.NewSimpleDockerBackend(ctx)
imageprefix := "foo/"
tmpdir, err := ioutil.TempDir(os.TempDir(), "artifact")

View File

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

View File

@ -45,7 +45,7 @@ type HashOptions struct {
func (c Checksums) List() (res [][]string) {
keys := make([]string, 0)
for k, _ := range c {
for k := range c {
keys = append(keys, k)
}
sort.Strings(keys)

View File

@ -1,6 +1,4 @@
// Copyright © 2019 Ettore Di Giacinto <mudler@gentoo.org>
// Daniele Rondina <geaaru@sabayonlinux.org>
// 2021 Ettore Di Giacinto <mudler@mocaccino.org>
// Copyright © 2019-2021 Ettore Di Giacinto <mudler@gentoo.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
@ -39,19 +37,22 @@ var AvailableResolvers = strings.Join([]string{solver.QLearningResolverType}, "
type LuetLoggingConfig struct {
// Path of the logfile
Path string `mapstructure:"path"`
Path string `yaml:"path" mapstructure:"path"`
// Enable/Disable logging to file
EnableLogFile bool `mapstructure:"enable_logfile"`
EnableLogFile bool `yaml:"enable_logfile" mapstructure:"enable_logfile"`
// Enable JSON format logging in file
JsonFormat bool `mapstructure:"json_format"`
JsonFormat bool `yaml:"json_format" mapstructure:"json_format"`
// Log level
Level LogLevel `mapstructure:"level"`
Level string `yaml:"level" mapstructure:"level"`
// Enable emoji
EnableEmoji bool `mapstructure:"enable_emoji"`
EnableEmoji bool `yaml:"enable_emoji" mapstructure:"enable_emoji"`
// Enable/Disable color in logging
Color bool `mapstructure:"color"`
Color bool `yaml:"color" mapstructure:"color"`
// NoSpinner disable spinner
NoSpinner bool `yaml:"no_spinner" mapstructure:"no_spinner"`
}
type LuetGeneralConfig struct {
@ -108,8 +109,42 @@ type LuetSystemConfig struct {
TmpDirBase string `yaml:"tmpdir_base" mapstructure:"tmpdir_base"`
}
func (s *LuetSystemConfig) SetRootFS(path string) error {
p, err := fileHelper.Rel2Abs(path)
// Init reads the config and replace user-defined paths with
// absolute paths where necessary, and construct the paths for the cache
// and database on the real system
func (c *LuetConfig) Init() error {
if err := c.System.init(); err != nil {
return err
}
if err := c.loadConfigProtect(); err != nil {
return err
}
// Load repositories
if err := c.loadRepositories(); err != nil {
return err
}
return nil
}
func (s *LuetSystemConfig) init() error {
if err := s.setRootfs(); err != nil {
return err
}
if err := s.setDBPath(); err != nil {
return err
}
s.setCachePath()
return nil
}
func (s *LuetSystemConfig) setRootfs() error {
p, err := fileHelper.Rel2Abs(s.Rootfs)
if err != nil {
return err
}
@ -118,9 +153,8 @@ func (s *LuetSystemConfig) SetRootFS(path string) error {
return nil
}
func (sc *LuetSystemConfig) GetRepoDatabaseDirPath(name string) string {
dbpath := filepath.Join(sc.Rootfs, sc.DatabasePath)
dbpath = filepath.Join(dbpath, "repos/"+name)
func (sc LuetSystemConfig) GetRepoDatabaseDirPath(name string) string {
dbpath := filepath.Join(sc.DatabasePath, "repos/"+name)
err := os.MkdirAll(dbpath, os.ModePerm)
if err != nil {
panic(err)
@ -128,45 +162,48 @@ func (sc *LuetSystemConfig) GetRepoDatabaseDirPath(name string) string {
return dbpath
}
func (sc *LuetSystemConfig) GetSystemRepoDatabaseDirPath() string {
func (sc *LuetSystemConfig) setDBPath() error {
dbpath := filepath.Join(sc.Rootfs,
sc.DatabasePath)
err := os.MkdirAll(dbpath, os.ModePerm)
if err != nil {
panic(err)
return err
}
return dbpath
sc.DatabasePath = dbpath
return nil
}
func (sc *LuetSystemConfig) GetSystemPkgsCacheDirPath() (p string) {
func (sc *LuetSystemConfig) setCachePath() {
var cachepath string
if sc.PkgsCachePath != "" {
cachepath = sc.PkgsCachePath
if !filepath.IsAbs(cachepath) {
cachepath = filepath.Join(sc.DatabasePath, sc.PkgsCachePath)
os.MkdirAll(cachepath, os.ModePerm)
} else {
cachepath = sc.PkgsCachePath
}
} else {
// Create dynamic cache for test suites
cachepath, _ = ioutil.TempDir(os.TempDir(), "cachepkgs")
}
if filepath.IsAbs(cachepath) {
p = cachepath
} else {
p = filepath.Join(sc.GetSystemRepoDatabaseDirPath(), cachepath)
}
sc.PkgsCachePath = cachepath // Be consistent with the path we set
return
}
func (sc *LuetSystemConfig) GetRootFsAbs() (string, error) {
return filepath.Abs(sc.Rootfs)
}
type LuetKV struct {
type FinalizerEnv struct {
Key string `json:"key" yaml:"key" mapstructure:"key"`
Value string `json:"value" yaml:"value" mapstructure:"value"`
}
type Finalizers []FinalizerEnv
func (f Finalizers) Slice() (sl []string) {
for _, kv := range f {
sl = append(sl, fmt.Sprintf("%s=%s", kv.Key, kv.Value))
}
return
}
type LuetConfig struct {
Logging LuetLoggingConfig `yaml:"logging,omitempty" mapstructure:"logging"`
General LuetGeneralConfig `yaml:"general,omitempty" mapstructure:"general"`
@ -179,16 +216,16 @@ type LuetConfig struct {
ConfigFromHost bool `yaml:"config_from_host,omitempty" mapstructure:"config_from_host"`
SystemRepositories LuetRepositories `yaml:"repositories,omitempty" mapstructure:"repositories"`
FinalizerEnvs []LuetKV `json:"finalizer_envs,omitempty" yaml:"finalizer_envs,omitempty" mapstructure:"finalizer_envs,omitempty"`
FinalizerEnvs Finalizers `json:"finalizer_envs,omitempty" yaml:"finalizer_envs,omitempty" mapstructure:"finalizer_envs,omitempty"`
ConfigProtectConfFiles []config.ConfigProtectConfFile `yaml:"-" mapstructure:"-"`
}
func (c *LuetConfig) GetSystemDB() pkg.PackageDatabase {
switch c.GetSystem().DatabaseEngine {
switch c.System.DatabaseEngine {
case "boltdb":
return pkg.NewBoltDatabase(
filepath.Join(c.GetSystem().GetSystemRepoDatabaseDirPath(), "luet.db"))
filepath.Join(c.System.DatabasePath, "luet.db"))
default:
return pkg.NewInMemoryDatabase(true)
}
@ -198,83 +235,30 @@ func (c *LuetConfig) AddSystemRepository(r LuetRepository) {
c.SystemRepositories = append(c.SystemRepositories, r)
}
func (c *LuetConfig) GetFinalizerEnvsMap() map[string]string {
ans := make(map[string]string)
for _, kv := range c.FinalizerEnvs {
ans[kv.Key] = kv.Value
}
return ans
}
func (c *LuetConfig) SetFinalizerEnv(k, v string) {
keyPresent := false
envs := []LuetKV{}
envs := []FinalizerEnv{}
for _, kv := range c.FinalizerEnvs {
if kv.Key == k {
keyPresent = true
envs = append(envs, LuetKV{Key: kv.Key, Value: v})
envs = append(envs, FinalizerEnv{Key: kv.Key, Value: v})
} else {
envs = append(envs, kv)
}
}
if !keyPresent {
envs = append(envs, LuetKV{Key: k, Value: v})
envs = append(envs, FinalizerEnv{Key: k, Value: v})
}
c.FinalizerEnvs = envs
}
func (c *LuetConfig) GetFinalizerEnvs() []string {
ans := []string{}
for _, kv := range c.FinalizerEnvs {
ans = append(ans, fmt.Sprintf("%s=%s", kv.Key, kv.Value))
}
return ans
}
func (c *LuetConfig) GetFinalizerEnv(k string) (string, error) {
keyNotPresent := true
ans := ""
for _, kv := range c.FinalizerEnvs {
if kv.Key == k {
keyNotPresent = false
ans = kv.Value
}
}
if keyNotPresent {
return "", errors.New("Finalizer key " + k + " not found")
}
return ans, nil
}
func (c *LuetConfig) GetLogging() *LuetLoggingConfig {
return &c.Logging
}
func (c *LuetConfig) GetGeneral() *LuetGeneralConfig {
return &c.General
}
func (c *LuetConfig) GetSystem() *LuetSystemConfig {
return &c.System
}
func (c *LuetConfig) GetSolverOptions() *LuetSolverOptions {
return &c.Solver
}
func (c *LuetConfig) YAML() ([]byte, error) {
return yaml.Marshal(c)
}
func (c *LuetConfig) GetConfigProtectConfFiles() []config.ConfigProtectConfFile {
return c.ConfigProtectConfFiles
}
func (c *LuetConfig) AddConfigProtectConfFile(file *config.ConfigProtectConfFile) {
func (c *LuetConfig) addProtectFile(file *config.ConfigProtectConfFile) {
if c.ConfigProtectConfFiles == nil {
c.ConfigProtectConfFiles = []config.ConfigProtectConfFile{*file}
} else {
@ -282,28 +266,21 @@ func (c *LuetConfig) AddConfigProtectConfFile(file *config.ConfigProtectConfFile
}
}
func (c *LuetConfig) LoadRepositories(ctx *Context) error {
func (c *LuetConfig) loadRepositories() 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
}
rootfs = c.System.Rootfs
}
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
}
@ -313,27 +290,20 @@ func (c *LuetConfig) LoadRepositories(ctx *Context) error {
}
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
}
@ -359,28 +329,20 @@ func (c *LuetConfig) GetSystemRepository(name string) (*LuetRepository, error) {
return ans, nil
}
func (c *LuetConfig) LoadConfigProtect(ctx *Context) error {
func (c *LuetConfig) loadConfigProtect() 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
}
rootfs = c.System.Rootfs
}
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
}
@ -390,38 +352,31 @@ func (c *LuetConfig) LoadConfigProtect(ctx *Context) error {
}
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)
r, err := loadConfigProtectConfFile(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)
c.addProtectFile(r)
}
}
return nil
}
func loadConfigProtectConFile(filename string, data []byte) (*config.ConfigProtectConfFile, error) {
func loadConfigProtectConfFile(filename string, data []byte) (*config.ConfigProtectConfFile, error) {
ans := config.NewConfigProtectConfFile(filename)
err := yaml.Unmarshal(data, &ans)
if err != nil {
@ -429,47 +384,3 @@ func loadConfigProtectConFile(filename string, data []byte) (*config.ConfigProte
}
return ans, nil
}
func (c *LuetLoggingConfig) SetLogLevel(s LogLevel) {
c.Level = s
}
func (c *LuetSystemConfig) InitTmpDir() error {
if !filepath.IsAbs(c.TmpDirBase) {
abs, err := fileHelper.Rel2Abs(c.TmpDirBase)
if err != nil {
return errors.Wrap(err, "while converting relative path to absolute path")
}
c.TmpDirBase = abs
}
if _, err := os.Stat(c.TmpDirBase); err != nil {
if os.IsNotExist(err) {
err = os.MkdirAll(c.TmpDirBase, os.ModePerm)
if err != nil {
return err
}
}
}
return nil
}
func (c *LuetSystemConfig) CleanupTmpDir() error {
return os.RemoveAll(c.TmpDirBase)
}
func (c *LuetSystemConfig) TempDir(pattern string) (string, error) {
err := c.InitTmpDir()
if err != nil {
return "", err
}
return ioutil.TempDir(c.TmpDirBase, pattern)
}
func (c *LuetSystemConfig) TempFile(pattern string) (*os.File, error) {
err := c.InitTmpDir()
if err != nil {
return nil, err
}
return ioutil.TempFile(c.TmpDirBase, pattern)
}

View File

@ -17,53 +17,86 @@
package types_test
import (
"io/ioutil"
"os"
"path/filepath"
"strings"
types "github.com/mudler/luet/pkg/api/core/types"
"github.com/mudler/luet/pkg/api/core/context"
"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)
Context("Inits paths", func() {
t, _ := ioutil.TempDir("", "tests")
defer os.RemoveAll(t)
c := &types.LuetConfig{
System: types.LuetSystemConfig{
Rootfs: t,
PkgsCachePath: "foo",
DatabasePath: "baz",
}}
It("sets default", func() {
err := c.Init()
Expect(err).ToNot(HaveOccurred())
Expect(c.System.Rootfs).To(Equal(t))
Expect(c.System.PkgsCachePath).To(Equal(filepath.Join(t, "baz", "foo")))
Expect(c.System.DatabasePath).To(Equal(filepath.Join(t, "baz")))
})
})
Context("Load Repository1", func() {
var ctx *context.Context
BeforeEach(func() {
ctx = context.NewContext(context.WithConfig(&types.LuetConfig{
RepositoriesConfDir: []string{
"../../../../tests/fixtures/repos.conf.d",
},
}))
ctx.Config.Init()
})
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"))
Expect(len(ctx.GetConfig().SystemRepositories)).Should(Equal(2))
Expect(ctx.GetConfig().SystemRepositories[0].Name).Should(Equal("test1"))
Expect(ctx.GetConfig().SystemRepositories[0].Priority).Should(Equal(999))
Expect(ctx.GetConfig().SystemRepositories[0].Type).Should(Equal("disk"))
Expect(len(ctx.GetConfig().SystemRepositories[0].Urls)).Should(Equal(1))
Expect(ctx.GetConfig().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"))
Expect(len(ctx.GetConfig().SystemRepositories)).Should(Equal(2))
Expect(ctx.GetConfig().SystemRepositories[1].Name).Should(Equal("test2"))
Expect(ctx.GetConfig().SystemRepositories[1].Priority).Should(Equal(1000))
Expect(ctx.GetConfig().SystemRepositories[1].Type).Should(Equal("disk"))
Expect(len(ctx.GetConfig().SystemRepositories[1].Urls)).Should(Equal(1))
Expect(ctx.GetConfig().SystemRepositories[1].Urls[0]).Should(Equal("tests/repos/test2"))
})
})
Context("Simple temporary directory creation", func() {
ctx := context.NewContext(context.WithConfig(&types.LuetConfig{
System: types.LuetSystemConfig{
TmpDirBase: os.TempDir() + "/tmpluet",
},
}))
BeforeEach(func() {
ctx = context.NewContext(context.WithConfig(&types.LuetConfig{
System: types.LuetSystemConfig{
TmpDirBase: os.TempDir() + "/tmpluet",
},
}))
})
It("Create Temporary directory", func() {
ctx := types.NewContext()
ctx.Config.GetSystem().TmpDirBase = os.TempDir() + "/tmpluet"
tmpDir, err := ctx.Config.GetSystem().TempDir("test1")
tmpDir, err := ctx.TempDir("test1")
Expect(err).ToNot(HaveOccurred())
Expect(strings.HasPrefix(tmpDir, filepath.Join(os.TempDir(), "tmpluet"))).To(BeTrue())
Expect(fileHelper.Exists(tmpDir)).To(BeTrue())
@ -72,11 +105,7 @@ var _ = Describe("Config", func() {
})
It("Create Temporary file", func() {
ctx := types.NewContext()
ctx.Config.GetSystem().TmpDirBase = os.TempDir() + "/tmpluet"
tmpFile, err := ctx.Config.GetSystem().TempFile("testfile1")
tmpFile, err := ctx.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())

View File

@ -15,417 +15,16 @@
package types
import (
"context"
"fmt"
"os"
"path"
"path/filepath"
"regexp"
"runtime"
"strings"
"sync"
type Context interface {
Logger
GarbageCollector
GetConfig() LuetConfig
Copy() Context
// SetAnnotation sets generic annotations to hold in a context
SetAnnotation(s string, i interface{})
"github.com/kyokomi/emoji"
"github.com/mudler/luet/pkg/helpers/terminal"
"github.com/pkg/errors"
"github.com/pterm/pterm"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
"golang.org/x/term"
)
// GetAnnotation gets generic annotations to hold in a context
GetAnnotation(s string) interface{}
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
name string
s *pterm.SpinnerPrinter
spinnerLock *sync.Mutex
z *zap.Logger
ProgressBar *pterm.ProgressbarPrinter
}
func NewContext() *Context {
return &Context{
spinnerLock: &sync.Mutex{},
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) WithName(name string) *Context {
newc := c.Copy()
newc.name = name
return newc
}
func (c *Context) Copy() *Context {
configCopy := *c.Config
configCopy.System = *c.Config.GetSystem()
configCopy.General = *c.Config.GetGeneral()
configCopy.Logging = *c.Config.GetLogging()
ctx := *c
ctxCopy := &ctx
ctxCopy.Config = &configCopy
return ctxCopy
}
// GetTerminalSize returns the width and the height of the active terminal.
func (c *Context) GetTerminalSize() (width, height int, err error) {
w, h, err := term.GetSize(int(os.Stdout.Fd()))
if w <= 0 {
w = 0
}
if h <= 0 {
h = 0
}
if err != nil {
err = errors.New("size not detectable")
}
return w, h, err
}
func (c *Context) Init() (err error) {
if c.IsTerminal {
if !c.Config.Logging.Color {
c.Debug("Disabling colors")
c.NoColor()
}
} else {
c.Debug("Not a terminal, disabling colors")
c.NoColor()
}
if c.Config.General.Quiet {
c.NoColor()
pterm.DisableStyling()
}
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:
levelMsg = message
case 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.name != "" {
levelMsg = fmt.Sprintf("[%s] %s", c.name, 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)
}
WithLoggingContext(s string) Context
}

View File

@ -0,0 +1,25 @@
// 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 "os"
type GarbageCollector interface {
Clean() error
TempDir(pattern string) (string, error)
TempFile(s string) (*os.File, error)
String() string
}

View File

@ -0,0 +1,41 @@
// 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
// Logger is a standard logging interface
type Logger interface {
Info(...interface{})
Success(...interface{})
Warning(...interface{})
Warn(...interface{})
Debug(...interface{})
Error(...interface{})
Fatal(...interface{})
Panic(...interface{})
Trace(...interface{})
Infof(string, ...interface{})
Warnf(string, ...interface{})
Debugf(string, ...interface{})
Errorf(string, ...interface{})
Fatalf(string, ...interface{})
Panicf(string, ...interface{})
Tracef(string, ...interface{})
SpinnerStop()
Spinner()
Ask() bool
Screen(string)
}

View File

@ -2,13 +2,13 @@ package compiler
import (
v1 "github.com/google/go-containerregistry/pkg/v1"
"github.com/mudler/luet/pkg/api/core/types"
"github.com/mudler/luet/pkg/api/core/types"
"github.com/mudler/luet/pkg/compiler/backend"
"github.com/pkg/errors"
)
func NewBackend(ctx *types.Context, s string) (CompilerBackend, error) {
func NewBackend(ctx types.Context, s string) (CompilerBackend, error) {
var compilerBackend CompilerBackend
switch s {

View File

@ -18,9 +18,8 @@ package backend
import (
"os/exec"
"github.com/mudler/luet/pkg/api/core/types"
"github.com/google/go-containerregistry/pkg/crane"
"github.com/mudler/luet/pkg/api/core/types"
"github.com/pkg/errors"
)
@ -43,9 +42,9 @@ type Options struct {
BackendArgs []string
}
func runCommand(ctx *types.Context, cmd *exec.Cmd) error {
func runCommand(ctx types.Context, cmd *exec.Cmd) error {
output := ""
buffered := !ctx.Config.GetGeneral().ShowBuildOutput
buffered := !ctx.GetConfig().General.ShowBuildOutput
writer := NewBackendWriter(buffered, ctx)
cmd.Stdout = writer

View File

@ -32,10 +32,10 @@ import (
)
type SimpleDocker struct {
ctx *types.Context
ctx types.Context
}
func NewSimpleDockerBackend(ctx *types.Context) *SimpleDocker {
func NewSimpleDockerBackend(ctx types.Context) *SimpleDocker {
return &SimpleDocker{ctx: ctx}
}
@ -190,7 +190,7 @@ func (s *SimpleDocker) imageFromCLIPipe(a string) (v1.Image, error) {
}
func (s *SimpleDocker) imageFromDisk(a string) (v1.Image, error) {
f, err := s.ctx.Config.GetSystem().TempFile("snapshot")
f, err := s.ctx.TempFile("snapshot")
if err != nil {
return nil, err
}

View File

@ -16,7 +16,7 @@
package backend_test
import (
"github.com/mudler/luet/pkg/api/core/types"
"github.com/mudler/luet/pkg/api/core/context"
. "github.com/mudler/luet/pkg/compiler"
"github.com/mudler/luet/pkg/compiler/backend"
. "github.com/mudler/luet/pkg/compiler/backend"
@ -34,7 +34,7 @@ import (
var _ = Describe("Docker backend", func() {
Context("Simple Docker backend satisfies main interface functionalities", func() {
ctx := types.NewContext()
ctx := context.NewContext()
It("Builds and generate tars", func() {
generalRecipe := tree.NewGeneralRecipe(pkg.NewInMemoryDatabase(false))

View File

@ -28,10 +28,10 @@ import (
)
type SimpleImg struct {
ctx *types.Context
ctx types.Context
}
func NewSimpleImgBackend(ctx *types.Context) *SimpleImg {
func NewSimpleImgBackend(ctx types.Context) *SimpleImg {
return &SimpleImg{ctx: ctx}
}
@ -77,7 +77,7 @@ func (s *SimpleImg) RemoveImage(opts Options) error {
func (s *SimpleImg) ImageReference(a string, ondisk bool) (v1.Image, error) {
f, err := s.ctx.Config.GetSystem().TempFile("snapshot")
f, err := s.ctx.TempFile("snapshot")
if err != nil {
return nil, err
}

View File

@ -25,10 +25,10 @@ import (
type BackendWriter struct {
BufferedOutput bool
Buffer *bytes.Buffer
ctx *types.Context
ctx types.Context
}
func NewBackendWriter(buffered bool, ctx *types.Context) *BackendWriter {
func NewBackendWriter(buffered bool, ctx types.Context) *BackendWriter {
return &BackendWriter{
BufferedOutput: buffered,
Buffer: &bytes.Buffer{},
@ -41,7 +41,7 @@ func (b *BackendWriter) Write(p []byte) (int, error) {
return b.Buffer.Write(p)
}
b.ctx.Msg("info", false, (string(p)))
b.ctx.Info((string(p)))
return len(p), nil
}

View File

@ -30,8 +30,8 @@ import (
"time"
bus "github.com/mudler/luet/pkg/api/core/bus"
"github.com/mudler/luet/pkg/api/core/context"
"github.com/mudler/luet/pkg/api/core/image"
"github.com/mudler/luet/pkg/api/core/types"
artifact "github.com/mudler/luet/pkg/api/core/types/artifact"
"github.com/mudler/luet/pkg/compiler/backend"
"github.com/mudler/luet/pkg/compiler/types/options"
@ -82,7 +82,7 @@ func NewLuetCompiler(backend CompilerBackend, db pkg.PackageDatabase, compilerOp
c := NewCompiler(compilerOpts...)
if c.Options.Context == nil {
c.Options.Context = types.NewContext()
c.Options.Context = context.NewContext()
}
// c.Options.BackendType
c.Backend = backend
@ -239,8 +239,10 @@ func (cs *LuetCompiler) unpackFs(concurrency int, keepPermissions bool, p *compi
return nil, err
}
ctx := cs.Options.Context.WithLoggingContext(fmt.Sprintf("extract %s", runnerOpts.ImageName))
_, rootfs, err := image.Extract(
cs.Options.Context,
ctx,
img,
image.ExtractFiles(
cs.Options.Context,
@ -273,7 +275,7 @@ func (cs *LuetCompiler) unpackFs(concurrency int, keepPermissions bool, p *compi
func (cs *LuetCompiler) unpackDelta(concurrency int, keepPermissions bool, p *compilerspec.LuetCompilationSpec, builderOpts, runnerOpts backend.Options) (*artifact.PackageArtifact, error) {
rootfs, err := cs.Options.Context.Config.System.TempDir("rootfs")
rootfs, err := cs.Options.Context.TempDir("rootfs")
if err != nil {
return nil, errors.Wrap(err, "Could not create tempdir")
}
@ -350,7 +352,7 @@ func (cs *LuetCompiler) buildPackageImage(image, buildertaggedImage, packageImag
p.SetSeedImage(image) // In this case, we ignore the build deps as we suppose that the image has them - otherwise we recompose the tree with a solver,
// and we build all the images first.
buildDir, err := cs.Options.Context.Config.System.TempDir("build")
buildDir, err := cs.Options.Context.TempDir("build")
if err != nil {
return builderOpts, runnerOpts, err
}
@ -458,7 +460,7 @@ func (cs *LuetCompiler) genArtifact(p *compilerspec.LuetCompilationSpec, builder
if p.EmptyPackage() {
fakePackage := p.Rel(p.GetPackage().GetFingerPrint() + ".package.tar")
rootfs, err = cs.Options.Context.Config.System.TempDir("rootfs")
rootfs, err = cs.Options.Context.TempDir("rootfs")
if err != nil {
return nil, errors.Wrap(err, "Could not create tempdir")
}
@ -939,7 +941,7 @@ func (cs *LuetCompiler) resolveFinalImages(concurrency int, keepPermissions bool
}
// otherwise, generate it and push it aside
joinDir, err := cs.Options.Context.Config.System.TempDir("join")
joinDir, err := cs.Options.Context.TempDir("join")
if err != nil {
return errors.Wrap(err, "could not create tempdir for joining images")
}
@ -978,7 +980,7 @@ func (cs *LuetCompiler) resolveFinalImages(concurrency int, keepPermissions bool
}
}
artifactDir, err := cs.Options.Context.Config.System.TempDir("join")
artifactDir, err := cs.Options.Context.TempDir("join")
if err != nil {
return errors.Wrap(err, "could not create tempdir for final artifact")
}
@ -1341,7 +1343,7 @@ func (cs *LuetCompiler) templatePackage(vals []map[string]interface{}, pack pkg.
} else {
bv := cs.Options.BuildValuesFile
if len(vals) > 0 {
valuesdir, err := cs.Options.Context.Config.System.TempDir("genvalues")
valuesdir, err := cs.Options.Context.TempDir("genvalues")
if err != nil {
return nil, errors.Wrap(err, "Could not create tempdir")
}

View File

@ -24,8 +24,8 @@ import (
helpers "github.com/mudler/luet/tests/helpers"
"github.com/mudler/luet/pkg/api/core/context"
"github.com/mudler/luet/pkg/api/core/image"
"github.com/mudler/luet/pkg/api/core/types"
"github.com/mudler/luet/pkg/api/core/types/artifact"
. "github.com/mudler/luet/pkg/compiler"
sd "github.com/mudler/luet/pkg/compiler/backend"
@ -40,7 +40,7 @@ import (
)
var _ = Describe("Compiler", func() {
ctx := types.NewContext()
ctx := context.NewContext()
Context("Simple package build definition", func() {
It("Compiles it correctly", func() {
@ -51,7 +51,7 @@ var _ = Describe("Compiler", func() {
Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(3))
compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase(), options.Concurrency(2), options.WithContext(types.NewContext()))
compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase(), options.Concurrency(2), options.WithContext(context.NewContext()))
spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"})
Expect(err).ToNot(HaveOccurred())
@ -94,7 +94,7 @@ var _ = Describe("Compiler", func() {
Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(3))
compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase(), options.Concurrency(2), options.WithContext(types.NewContext()))
compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase(), options.Concurrency(2), options.WithContext(context.NewContext()))
spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "c", Category: "test", Version: "1.2"})
Expect(err).ToNot(HaveOccurred())
@ -124,7 +124,7 @@ var _ = Describe("Compiler", func() {
Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(3))
compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase(), options.Concurrency(2), options.WithContext(types.NewContext()))
compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase(), options.Concurrency(2), options.WithContext(context.NewContext()))
spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "c", Category: "test", Version: "1.2"})
Expect(err).ToNot(HaveOccurred())
@ -156,7 +156,7 @@ var _ = Describe("Compiler", func() {
Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(3))
compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase(), options.Concurrency(1), options.WithContext(types.NewContext()))
compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase(), options.Concurrency(1), options.WithContext(context.NewContext()))
spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"})
Expect(err).ToNot(HaveOccurred())
@ -190,7 +190,7 @@ var _ = Describe("Compiler", func() {
err = generalRecipe.Load("../../tests/fixtures/templates")
Expect(err).ToNot(HaveOccurred())
compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase(), options.WithContext(types.NewContext()))
compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase(), options.WithContext(context.NewContext()))
Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(1))
pkg, err := generalRecipe.GetDatabase().FindPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"})
@ -214,7 +214,7 @@ var _ = Describe("Compiler", func() {
Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(4))
compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase(), options.Concurrency(2), options.WithContext(types.NewContext()))
compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase(), options.Concurrency(2), options.WithContext(context.NewContext()))
spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "c", Category: "test", Version: "1.0"})
Expect(err).ToNot(HaveOccurred())
@ -270,7 +270,7 @@ var _ = Describe("Compiler", func() {
Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(2))
compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase(), options.Concurrency(1), options.WithContext(types.NewContext()))
compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase(), options.Concurrency(1), options.WithContext(context.NewContext()))
spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "extra", Category: "layer", Version: "1.0"})
Expect(err).ToNot(HaveOccurred())
@ -794,7 +794,7 @@ var _ = Describe("Compiler", func() {
Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(3))
compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase(), options.Concurrency(2), options.WithContext(types.NewContext()))
compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase(), options.Concurrency(2), options.WithContext(context.NewContext()))
spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "c", Category: "test", Version: "1.0"})
Expect(err).ToNot(HaveOccurred())
@ -983,7 +983,7 @@ var _ = Describe("Compiler", func() {
Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(2))
compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase(), options.WithContext(types.NewContext()))
compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase(), options.WithContext(context.NewContext()))
spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "runtime", Category: "layer", Version: "0.1"})
Expect(err).ToNot(HaveOccurred())
@ -1018,7 +1018,7 @@ var _ = Describe("Compiler", func() {
err := generalRecipe.Load("../../tests/fixtures/includeimage")
Expect(err).ToNot(HaveOccurred())
Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(2))
compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase(), options.WithContext(types.NewContext()))
compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase(), options.WithContext(context.NewContext()))
specs, err := compiler.FromDatabase(generalRecipe.GetDatabase(), true, "")
Expect(err).ToNot(HaveOccurred())
@ -1037,7 +1037,7 @@ var _ = Describe("Compiler", func() {
Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(2))
compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase(), options.WithContext(types.NewContext()))
compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase(), options.WithContext(context.NewContext()))
spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "runtime", Category: "layer", Version: "0.1"})
Expect(err).ToNot(HaveOccurred())

View File

@ -16,7 +16,7 @@
package compiler_test
import (
"github.com/mudler/luet/pkg/api/core/types"
"github.com/mudler/luet/pkg/api/core/context"
. "github.com/mudler/luet/pkg/compiler"
sd "github.com/mudler/luet/pkg/compiler/backend"
"github.com/mudler/luet/pkg/compiler/types/options"
@ -27,7 +27,7 @@ import (
)
var _ = Describe("ImageHashTree", func() {
ctx := types.NewContext()
ctx := context.NewContext()
generalRecipe := tree.NewCompilerRecipe(pkg.NewInMemoryDatabase(false))
compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase(), options.Concurrency(2))
hashtree := NewHashTree(generalRecipe.GetDatabase())

View File

@ -53,7 +53,7 @@ type Compiler struct {
// Image repository to push to
PushFinalImagesRepository string
Context *types.Context
Context types.Context
}
func NewDefaultCompiler() *Compiler {
@ -237,7 +237,7 @@ func WithSolverOptions(c types.LuetSolverOptions) func(cfg *Compiler) error {
}
}
func WithContext(c *types.Context) func(cfg *Compiler) error {
func WithContext(c types.Context) func(cfg *Compiler) error {
return func(cfg *Compiler) error {
cfg.Context = c
return nil

View File

@ -127,7 +127,7 @@ type UnpackEventData struct {
}
// DownloadAndExtractDockerImage extracts a container image natively. It supports privileged/unprivileged mode
func DownloadAndExtractDockerImage(ctx *luettypes.Context, image, dest string, auth *types.AuthConfig, verify bool) (*images.Image, error) {
func DownloadAndExtractDockerImage(ctx luettypes.Context, image, dest string, auth *types.AuthConfig, verify bool) (*images.Image, error) {
if verify {
img, err := verifyImage(image, auth)
if err != nil {

View File

@ -1,12 +0,0 @@
// +build darwin dragonfly freebsd netbsd openbsd
package terminal
import "golang.org/x/sys/unix"
const ioctlReadTermios = unix.TIOCGETA
func isTerminal(fd int) bool {
_, err := unix.IoctlGetTermios(fd, ioctlReadTermios)
return err == nil
}

View File

@ -1,17 +0,0 @@
// +build !windows,!nacl,!plan9
package terminal
import (
"io"
"os"
)
func IsTerminal(w io.Writer) bool {
switch v := w.(type) {
case *os.File:
return isTerminal(int(v.Fd()))
default:
return false
}
}

View File

@ -1,11 +0,0 @@
// +build js nacl plan9
package terminal
import (
"io"
)
func IsTerminal(w io.Writer) bool {
return false
}

View File

@ -1,11 +0,0 @@
package terminal
import (
"golang.org/x/sys/unix"
)
// IsTerminal returns true if the given file descriptor is a terminal.
func isTerminal(fd int) bool {
_, err := unix.IoctlGetTermio(fd, unix.TCGETA)
return err == nil
}

View File

@ -1,12 +0,0 @@
// +build linux aix zos
package terminal
import "golang.org/x/sys/unix"
const ioctlReadTermios = unix.TCGETS
func isTerminal(fd int) bool {
_, err := unix.IoctlGetTermios(fd, ioctlReadTermios)
return err == nil
}

View File

@ -1,27 +0,0 @@
// +build windows
package terminal
import (
"io"
"os"
"golang.org/x/sys/windows"
)
func IsTerminal(w io.Writer) bool {
switch v := w.(type) {
case *os.File:
handle := windows.Handle(v.Fd())
var mode uint32
if err := windows.GetConsoleMode(handle, &mode); err != nil {
return false
}
mode |= windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING
if err := windows.SetConsoleMode(handle, mode); err != nil {
return false
}
return true
}
return false
}

View File

@ -24,9 +24,9 @@ import (
"github.com/docker/docker/api/types"
"github.com/docker/go-units"
luettypes "github.com/mudler/luet/pkg/api/core/types"
"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/helpers"
@ -42,17 +42,17 @@ type DockerClient struct {
RepoData RepoData
auth *types.AuthConfig
Cache *artifact.ArtifactCache
context *luetTypes.Context
context luettypes.Context
}
func NewDockerClient(r RepoData, ctx *luetTypes.Context) *DockerClient {
func NewDockerClient(r RepoData, ctx luettypes.Context) *DockerClient {
auth := &types.AuthConfig{}
dat, _ := json.Marshal(r.Authentication)
json.Unmarshal(dat, auth)
return &DockerClient{RepoData: r, auth: auth,
Cache: artifact.NewCache(ctx.Config.GetSystem().GetSystemPkgsCacheDirPath()),
Cache: artifact.NewCache(ctx.GetConfig().System.PkgsCachePath),
context: ctx,
}
}
@ -81,13 +81,13 @@ func (c *DockerClient) DownloadArtifact(a *artifact.PackageArtifact) (*artifact.
// We discard checksum, that are checked while during pull and unpack by containerd
resultingArtifact.Checksums = artifact.Checksums{}
temp, err := c.context.Config.GetSystem().TempDir("image")
temp, err := c.context.TempDir("image")
if err != nil {
return nil, err
}
defer os.RemoveAll(temp)
tempArtifact, err := c.context.Config.GetSystem().TempFile("artifact")
tempArtifact, err := c.context.TempFile("artifact")
if err != nil {
return nil, err
}
@ -144,13 +144,13 @@ func (c *DockerClient) DownloadFile(name string) (string, error) {
// Files should be in URI/repository:<file>
ok := false
temp, err = c.context.Config.GetSystem().TempDir("tree")
temp, err = c.context.TempDir("tree")
if err != nil {
return "", err
}
for _, uri := range c.RepoData.Urls {
file, err = c.context.Config.GetSystem().TempFile("DockerClient")
file, err = c.context.TempFile("DockerClient")
if err != nil {
continue
}

View File

@ -20,7 +20,7 @@ import (
"os"
"path/filepath"
"github.com/mudler/luet/pkg/api/core/types"
"github.com/mudler/luet/pkg/api/core/context"
"github.com/mudler/luet/pkg/api/core/types/artifact"
compilerspec "github.com/mudler/luet/pkg/compiler/types/spec"
fileHelper "github.com/mudler/luet/pkg/helpers/file"
@ -38,7 +38,7 @@ import (
// mount/unmount layers.
var _ = Describe("Docker client", func() {
Context("With repository", func() {
ctx := types.NewContext()
ctx := context.NewContext()
repoImage := os.Getenv("UNIT_TEST_DOCKER_IMAGE")
var repoURL []string

View File

@ -36,13 +36,13 @@ import (
type HttpClient struct {
RepoData RepoData
Cache *artifact.ArtifactCache
context *types.Context
context types.Context
}
func NewHttpClient(r RepoData, ctx *types.Context) *HttpClient {
func NewHttpClient(r RepoData, ctx types.Context) *HttpClient {
return &HttpClient{
RepoData: r,
Cache: artifact.NewCache(ctx.Config.GetSystem().GetSystemPkgsCacheDirPath()),
Cache: artifact.NewCache(ctx.GetConfig().System.PkgsCachePath),
context: ctx,
}
}
@ -85,16 +85,16 @@ func Round(input float64) float64 {
func (c *HttpClient) DownloadFile(p string) (string, error) {
var file *os.File = nil
var downloaded bool
temp, err := c.context.Config.GetSystem().TempDir("download")
temp, err := c.context.TempDir("download")
if err != nil {
return "", err
}
defer os.RemoveAll(temp)
client := NewGrabClient(c.context.Config.General.HTTPTimeout)
client := NewGrabClient(c.context.GetConfig().General.HTTPTimeout)
for _, uri := range c.RepoData.Urls {
file, err = c.context.Config.GetSystem().TempFile("HttpClient")
file, err = c.context.TempFile("HttpClient")
if err != nil {
c.context.Debug("Failed downloading", p, "from", uri)
@ -117,9 +117,12 @@ func (c *HttpClient) DownloadFile(p string) (string, error) {
// Initialize a progressbar only if we have one in the current context
var pb *pterm.ProgressbarPrinter
if c.context.ProgressBar != nil {
pb, _ = c.context.ProgressBar.WithTotal(int(resp.Size())).WithTitle(filepath.Base(resp.Request.HTTPRequest.URL.RequestURI())).Start()
pbb := c.context.GetAnnotation("progressbar")
switch v := pbb.(type) {
case *pterm.ProgressbarPrinter:
pb, _ = v.WithTotal(int(resp.Size())).WithTitle(filepath.Base(resp.Request.HTTPRequest.URL.RequestURI())).Start()
}
// start download loop
t := time.NewTicker(500 * time.Millisecond)
defer t.Stop()

View File

@ -22,7 +22,7 @@ import (
"os"
"path/filepath"
"github.com/mudler/luet/pkg/api/core/types"
"github.com/mudler/luet/pkg/api/core/context"
"github.com/mudler/luet/pkg/api/core/types/artifact"
fileHelper "github.com/mudler/luet/pkg/helpers/file"
. "github.com/mudler/luet/pkg/installer/client"
@ -32,7 +32,7 @@ import (
var _ = Describe("Http client", func() {
Context("With repository", func() {
ctx := types.NewContext()
ctx := context.NewContext()
It("Downloads single files", func() {
// setup small staticfile webserver with content

View File

@ -29,12 +29,12 @@ import (
type LocalClient struct {
RepoData RepoData
Cache *artifact.ArtifactCache
context *types.Context
context types.Context
}
func NewLocalClient(r RepoData, ctx *types.Context) *LocalClient {
func NewLocalClient(r RepoData, ctx types.Context) *LocalClient {
return &LocalClient{
Cache: artifact.NewCache(ctx.Config.GetSystem().GetSystemPkgsCacheDirPath()),
Cache: artifact.NewCache(ctx.GetConfig().System.PkgsCachePath),
RepoData: r,
context: ctx,
}
@ -78,11 +78,8 @@ func (c *LocalClient) DownloadFile(name string) (string, error) {
rootfs := ""
if !c.context.Config.ConfigFromHost {
rootfs, err = c.context.Config.GetSystem().GetRootFsAbs()
if err != nil {
return "", err
}
if !c.context.GetConfig().ConfigFromHost {
rootfs = c.context.GetConfig().System.Rootfs
}
ok := false
@ -91,7 +88,7 @@ func (c *LocalClient) DownloadFile(name string) (string, error) {
uri = filepath.Join(rootfs, uri)
c.context.Info("Copying file", name, "from", uri)
file, err = c.context.Config.GetSystem().TempFile("localclient")
file, err = c.context.TempFile("localclient")
if err != nil {
continue
}

View File

@ -20,7 +20,7 @@ import (
"os"
"path/filepath"
"github.com/mudler/luet/pkg/api/core/types"
"github.com/mudler/luet/pkg/api/core/context"
"github.com/mudler/luet/pkg/api/core/types/artifact"
fileHelper "github.com/mudler/luet/pkg/helpers/file"
. "github.com/mudler/luet/pkg/installer/client"
@ -30,7 +30,7 @@ import (
var _ = Describe("Local client", func() {
Context("With repository", func() {
ctx := types.NewContext()
ctx := context.NewContext()
It("Downloads single files", func() {
tmpdir, err := ioutil.TempDir("", "test")

View File

@ -32,7 +32,7 @@ type LuetFinalizer struct {
Uninstall []string `json:"uninstall"` // TODO: Where to store?
}
func (f *LuetFinalizer) RunInstall(ctx *types.Context, s *System) error {
func (f *LuetFinalizer) RunInstall(ctx types.Context, s *System) error {
var cmd string
var args []string
if len(f.Shell) == 0 {
@ -51,14 +51,14 @@ func (f *LuetFinalizer) RunInstall(ctx *types.Context, s *System) error {
ctx.Info(":shell: Executing finalizer on ", s.Target, cmd, toRun)
if s.Target == string(os.PathSeparator) {
cmd := exec.Command(cmd, toRun...)
cmd.Env = ctx.Config.GetFinalizerEnvs()
cmd.Env = ctx.GetConfig().FinalizerEnvs.Slice()
stdoutStderr, err := cmd.CombinedOutput()
if err != nil {
return errors.Wrap(err, "Failed running command: "+string(stdoutStderr))
}
ctx.Info(string(stdoutStderr))
} else {
b := box.NewBox(cmd, toRun, []string{}, ctx.Config.GetFinalizerEnvs(), s.Target, false, true, true)
b := box.NewBox(cmd, toRun, []string{}, ctx.GetConfig().FinalizerEnvs.Slice(), s.Target, false, true, true)
err := b.Run()
if err != nil {
return errors.Wrap(err, "Failed running command ")
@ -69,7 +69,7 @@ func (f *LuetFinalizer) RunInstall(ctx *types.Context, s *System) error {
}
// TODO: We don't store uninstall finalizers ?!
func (f *LuetFinalizer) RunUnInstall(ctx *types.Context) error {
func (f *LuetFinalizer) RunUnInstall(ctx types.Context) error {
for _, c := range f.Uninstall {
ctx.Debug("finalizer:", "sh", "-c", c)
cmd := exec.Command("sh", "-c", c)

View File

@ -25,6 +25,7 @@ import (
"sync"
"github.com/mudler/luet/pkg/api/core/config"
"github.com/mudler/luet/pkg/api/core/logger"
"github.com/mudler/luet/pkg/api/core/bus"
"github.com/mudler/luet/pkg/api/core/types"
@ -54,7 +55,7 @@ type LuetInstallerOptions struct {
PackageRepositories types.LuetRepositories
AutoOSCheck bool
Context *types.Context
Context types.Context
}
type LuetInstaller struct {
@ -737,13 +738,15 @@ func (l *LuetInstaller) download(syncedRepos Repositories, toDownload map[string
// Check if the terminal is big enough to display a progress bar
// https://github.com/pterm/pterm/blob/4c725e56bfd9eb38e1c7b9dec187b50b93baa8bd/progressbar_printer.go#L190
w, _, err := ctx.GetTerminalSize()
w, _, err := logger.GetTerminalSize()
var pb *pterm.ProgressbarPrinter
if ctx.IsTerminal && err == nil && w > 100 {
if logger.IsTerminal() && err == nil && w > 100 {
area, _ := pterm.DefaultArea.Start()
ctx.ProgressBar = pterm.DefaultProgressbar.WithPrintTogether(area).WithTotal(len(toDownload)).WithTitle("Downloading packages")
pb, _ = ctx.ProgressBar.Start()
pb = pterm.DefaultProgressbar.WithPrintTogether(area).WithTotal(len(toDownload)).WithTitle("Downloading packages")
pb, _ = pb.Start()
ctx.SetAnnotation("progressbar", pb)
defer area.Stop()
}
@ -1046,7 +1049,7 @@ func (l *LuetInstaller) install(o Option, syncedRepos Repositories, toInstall ma
return s.ExecuteFinalizers(l.Options.Context, toFinalize)
}
func (l *LuetInstaller) getPackage(a ArtifactMatch, ctx *types.Context) (artifact *artifact.PackageArtifact, err error) {
func (l *LuetInstaller) getPackage(a ArtifactMatch, ctx types.Context) (artifact *artifact.PackageArtifact, err error) {
cli := a.Repository.Client(ctx)
@ -1084,7 +1087,7 @@ func (l *LuetInstaller) installPackage(m ArtifactMatch, s *System) error {
return s.Database.SetPackageFiles(&pkg.PackageFile{PackageFingerprint: m.Package.GetFingerPrint(), Files: files})
}
func (l *LuetInstaller) downloadWorker(i int, wg *sync.WaitGroup, pb *pterm.ProgressbarPrinter, c <-chan ArtifactMatch, ctx *types.Context) error {
func (l *LuetInstaller) downloadWorker(i int, wg *sync.WaitGroup, pb *pterm.ProgressbarPrinter, c <-chan ArtifactMatch, ctx types.Context) error {
defer wg.Done()
for p := range c {
@ -1114,7 +1117,7 @@ func (l *LuetInstaller) installerWorker(i int, wg *sync.WaitGroup, installLock *
installLock.Unlock()
if err != nil && !l.Options.Force {
//TODO: Uninstall, rollback.
l.Options.Context.Fatal("Failed installing package "+p.Package.GetName(), err.Error())
l.Options.Context.Error("Failed installing package "+p.Package.GetName(), err.Error())
return errors.Wrap(err, "Failed installing package "+p.Package.GetName())
}
if err == nil {
@ -1127,7 +1130,7 @@ func (l *LuetInstaller) installerWorker(i int, wg *sync.WaitGroup, installLock *
return nil
}
func checkAndPrunePath(ctx *types.Context, target, path string) {
func checkAndPrunePath(ctx types.Context, target, path string) {
// check if now the target path is empty
targetPath := filepath.Dir(path)
@ -1159,7 +1162,7 @@ func checkAndPrunePath(ctx *types.Context, target, path string) {
}
// We will try to cleanup every path from the file, if the folders left behind are empty
func pruneEmptyFilePath(ctx *types.Context, target string, path string) {
func pruneEmptyFilePath(ctx types.Context, target string, path string) {
checkAndPrunePath(ctx, target, path)
// A path is for e.g. /usr/bin/bar
@ -1193,7 +1196,7 @@ func (l *LuetInstaller) uninstall(p pkg.Package, s *System) error {
return errors.Wrap(err, "Failed getting installed files")
}
if !l.Options.Context.Config.ConfigProtectSkip {
if !l.Options.Context.GetConfig().ConfigProtectSkip {
if p.HasAnnotation(string(pkg.ConfigProtectAnnnotation)) {
dir, ok := p.GetAnnotations()[string(pkg.ConfigProtectAnnnotation)]
@ -1203,7 +1206,7 @@ func (l *LuetInstaller) uninstall(p pkg.Package, s *System) error {
}
cp = config.NewConfigProtect(annotationDir)
cp.Map(files, l.Options.Context.Config.GetConfigProtectConfFiles())
cp.Map(files, l.Options.Context.GetConfig().ConfigProtectConfFiles)
}
toRemove, notPresent := fileHelper.OrderFiles(s.Target, files)
@ -1212,15 +1215,15 @@ func (l *LuetInstaller) uninstall(p pkg.Package, s *System) error {
for _, f := range toRemove {
target := filepath.Join(s.Target, f)
if !l.Options.Context.Config.ConfigProtectSkip && cp.Protected(f) {
if !l.Options.Context.GetConfig().ConfigProtectSkip && cp.Protected(f) {
l.Options.Context.Debug("Preserving protected file:", f)
continue
}
l.Options.Context.Debug("Removing", target)
if l.Options.PreserveSystemEssentialData &&
strings.HasPrefix(f, l.Options.Context.Config.GetSystem().GetSystemPkgsCacheDirPath()) ||
strings.HasPrefix(f, l.Options.Context.Config.GetSystem().GetSystemRepoDatabaseDirPath()) {
strings.HasPrefix(f, l.Options.Context.GetConfig().System.PkgsCachePath) ||
strings.HasPrefix(f, l.Options.Context.GetConfig().System.DatabasePath) {
l.Options.Context.Warning("Preserve ", f, " which is required by luet ( you have to delete it manually if you really need to)")
continue
}
@ -1254,7 +1257,7 @@ func (l *LuetInstaller) uninstall(p pkg.Package, s *System) error {
for _, f := range notPresent {
target := filepath.Join(s.Target, f)
if !l.Options.Context.Config.ConfigProtectSkip && cp.Protected(f) {
if !l.Options.Context.GetConfig().ConfigProtectSkip && cp.Protected(f) {
l.Options.Context.Debug("Preserving protected file:", f)
continue
}

View File

@ -21,6 +21,7 @@ import (
"path/filepath"
// . "github.com/mudler/luet/pkg/installer"
"github.com/mudler/luet/pkg/api/core/context"
"github.com/mudler/luet/pkg/api/core/types"
compiler "github.com/mudler/luet/pkg/compiler"
backend "github.com/mudler/luet/pkg/compiler/backend"
@ -45,16 +46,16 @@ func stubRepo(tmpdir, tree string) (*LuetSystemRepository, error) {
WithPriority(1),
WithSource(tmpdir),
WithTree(tree),
WithContext(types.NewContext()),
WithContext(context.NewContext()),
WithDatabase(pkg.NewInMemoryDatabase(false)),
)
}
var _ = Describe("Installer", func() {
ctx := types.NewContext()
ctx := context.NewContext()
BeforeEach(func() {
ctx = types.NewContext()
ctx = context.NewContext()
})
Context("Writes a repository definition", func() {

View File

@ -115,11 +115,11 @@ func SystemRepositories(t types.LuetRepositories) Repositories {
}
// LoadBuildTree loads to the tree the compilation specs from the system repositories
func LoadBuildTree(t tree.Builder, db pkg.PackageDatabase, ctx *types.Context) error {
func LoadBuildTree(t tree.Builder, db pkg.PackageDatabase, ctx types.Context) error {
var reserr error
repos := SystemRepositories(ctx.Config.SystemRepositories)
repos := SystemRepositories(ctx.GetConfig().SystemRepositories)
for _, r := range repos {
repodir, err := ctx.Config.GetSystem().TempDir(r.Name)
repodir, err := ctx.TempDir(r.Name)
if err != nil {
reserr = multierr.Append(reserr, err)
}
@ -378,7 +378,7 @@ func (r *LuetSystemRepository) SetPriority(n int) {
r.LuetRepository.Priority = n
}
func (r *LuetSystemRepository) initialize(ctx *types.Context, src string) error {
func (r *LuetSystemRepository) initialize(ctx types.Context, src string) error {
generator, err := r.getGenerator(ctx, r.snapshotID)
if err != nil {
return errors.Wrap(err, "while constructing repository generator")
@ -526,12 +526,12 @@ func (r *LuetSystemRepository) BumpRevision(repospec string, resetRevision bool)
// 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
func (r *LuetSystemRepository) AddMetadata(ctx *types.Context, 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
meta, serialized := r.Serialize()
// Create metadata file and repository file
metaTmpDir, err := ctx.Config.GetSystem().TempDir("metadata")
metaTmpDir, err := ctx.TempDir("metadata")
defer os.RemoveAll(metaTmpDir) // clean up
if err != nil {
return nil, errors.Wrap(err, "Error met while creating tempdir for metadata")
@ -564,9 +564,9 @@ func (r *LuetSystemRepository) AddMetadata(ctx *types.Context, repospec, dst str
// AddTree adds a tree.Builder with the given key to the repository.
// It will generate an artifact which will be then embedded in the repository manifest
// It returns the generated artifacts and an error
func (r *LuetSystemRepository) AddTree(ctx *types.Context, t tree.Builder, dst, key string, defaults LuetRepositoryFile) (*artifact.PackageArtifact, error) {
func (r *LuetSystemRepository) AddTree(ctx types.Context, t tree.Builder, dst, key string, defaults LuetRepositoryFile) (*artifact.PackageArtifact, error) {
// Create tree and repository file
archive, err := ctx.Config.GetSystem().TempDir("archive")
archive, err := ctx.TempDir("archive")
if err != nil {
return nil, errors.Wrap(err, "Error met while creating tempdir for archive")
}
@ -710,7 +710,7 @@ type RepositoryGenerator interface {
Initialize(string, pkg.PackageDatabase) ([]*artifact.PackageArtifact, error)
}
func (r *LuetSystemRepository) getGenerator(ctx *types.Context, snapshotID string) (RepositoryGenerator, error) {
func (r *LuetSystemRepository) getGenerator(ctx types.Context, snapshotID string) (RepositoryGenerator, error) {
if snapshotID == "" {
snapshotID = time.Now().Format("20060102150405")
}
@ -735,7 +735,7 @@ func (r *LuetSystemRepository) getGenerator(ctx *types.Context, snapshotID strin
}
// Write writes the repository metadata to the supplied destination
func (r *LuetSystemRepository) Write(ctx *types.Context, dst string, resetRevision, force bool) error {
func (r *LuetSystemRepository) Write(ctx types.Context, dst string, resetRevision, force bool) error {
rg, err := r.getGenerator(ctx, r.snapshotID)
if err != nil {
return err
@ -744,7 +744,7 @@ func (r *LuetSystemRepository) Write(ctx *types.Context, dst string, resetRevisi
return rg.Generate(r, dst, resetRevision)
}
func (r *LuetSystemRepository) Client(ctx *types.Context) Client {
func (r *LuetSystemRepository) Client(ctx types.Context) Client {
switch r.GetType() {
case DiskRepositoryType:
return client.NewLocalClient(client.RepoData{Urls: r.GetUrls()}, ctx)
@ -803,7 +803,7 @@ func (r *LuetSystemRepository) getRepoFile(c Client, key string) (*artifact.Pack
}
func (r *LuetSystemRepository) SyncBuildMetadata(ctx *types.Context, path string) error {
func (r *LuetSystemRepository) SyncBuildMetadata(ctx types.Context, path string) error {
repo, err := r.Sync(ctx, false)
if err != nil {
@ -852,11 +852,11 @@ func (r *LuetSystemRepository) referenceID() string {
return repositoryReferenceID
}
func (r *LuetSystemRepository) Sync(ctx *types.Context, force bool) (*LuetSystemRepository, error) {
func (r *LuetSystemRepository) Sync(ctx types.Context, force bool) (*LuetSystemRepository, error) {
var repoUpdated bool = false
var treefs, metafs string
repobasedir := ctx.Config.GetSystem().GetRepoDatabaseDirPath(r.GetName())
repobasedir := ctx.GetConfig().System.GetRepoDatabaseDirPath(r.GetName())
toTimeSync := false
dat, err := ioutil.ReadFile(filepath.Join(repobasedir, "SYNCTIME"))
@ -923,11 +923,11 @@ func (r *LuetSystemRepository) Sync(ctx *types.Context, force bool) (*LuetSystem
}
} else {
treefs, err = ctx.Config.GetSystem().TempDir("treefs")
treefs, err = ctx.TempDir("treefs")
if err != nil {
return nil, errors.Wrap(err, "Error met while creating tempdir for rootfs")
}
metafs, err = ctx.Config.GetSystem().TempDir("metafs")
metafs, err = ctx.TempDir("metafs")
if err != nil {
return nil, errors.Wrap(err, "Error met whilte creating tempdir for metafs")
}

View File

@ -40,7 +40,7 @@ type dockerRepositoryGenerator struct {
b compiler.CompilerBackend
imagePrefix, snapshotID string
imagePush, force bool
context *types.Context
context types.Context
}
func (l *dockerRepositoryGenerator) Initialize(path string, db pkg.PackageDatabase) ([]*artifact.PackageArtifact, error) {
@ -115,7 +115,7 @@ func (l *dockerRepositoryGenerator) Initialize(path string, db pkg.PackageDataba
return art, nil
}
func pushImage(ctx *types.Context, 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 {
ctx.Debug("Image", image, "already present, skipping")
return nil
@ -138,7 +138,7 @@ func (d *dockerRepositoryGenerator) pushFileFromArtifact(a *artifact.PackageArti
func (d *dockerRepositoryGenerator) pushRepoMetadata(repospec, tag string, r *LuetSystemRepository) error {
// create temp dir for metafile
metaDir, err := d.context.Config.GetSystem().TempDir("metadata")
metaDir, err := d.context.TempDir("metadata")
if err != nil {
return errors.Wrap(err, "Error met while creating tempdir for metadata")
}
@ -184,7 +184,7 @@ func (d *dockerRepositoryGenerator) Generate(r *LuetSystemRepository, imagePrefi
r.LastUpdate = strconv.FormatInt(time.Now().Unix(), 10)
repoTemp, err := d.context.Config.GetSystem().TempDir("repo")
repoTemp, err := d.context.TempDir("repo")
if err != nil {
return errors.Wrap(err, "error met while creating tempdir for repository")
}

View File

@ -33,7 +33,7 @@ import (
)
type localRepositoryGenerator struct {
context *types.Context
context types.Context
snapshotID string
}
@ -41,7 +41,7 @@ func (l *localRepositoryGenerator) Initialize(path string, db pkg.PackageDatabas
return buildPackageIndex(l.context, path, db)
}
func buildPackageIndex(ctx *types.Context, 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 ff = func(currentpath string, info os.FileInfo, err error) error {

View File

@ -33,7 +33,7 @@ type RepositoryConfig struct {
CompilerBackend compiler.CompilerBackend
ImagePrefix string
context *types.Context
context types.Context
PushImages, Force, FromRepository, FromMetadata bool
}
@ -51,7 +51,7 @@ func (cfg *RepositoryConfig) Apply(opts ...RepositoryOption) error {
return nil
}
func WithContext(c *types.Context) func(cfg *RepositoryConfig) error {
func WithContext(c types.Context) func(cfg *RepositoryConfig) error {
return func(cfg *RepositoryConfig) error {
cfg.context = c
return nil

View File

@ -24,6 +24,7 @@ import (
"os"
"path/filepath"
"github.com/mudler/luet/pkg/api/core/context"
"github.com/mudler/luet/pkg/api/core/types"
artifact "github.com/mudler/luet/pkg/api/core/types/artifact"
"github.com/mudler/luet/pkg/compiler"
@ -49,16 +50,16 @@ func dockerStubRepo(tmpdir, tree, image string, push, force bool) (*LuetSystemRe
WithSource(tmpdir),
WithTree(tree),
WithDatabase(pkg.NewInMemoryDatabase(false)),
WithCompilerBackend(backend.NewSimpleDockerBackend(types.NewContext())),
WithCompilerBackend(backend.NewSimpleDockerBackend(context.NewContext())),
WithImagePrefix(image),
WithPushImages(push),
WithContext(types.NewContext()),
WithContext(context.NewContext()),
WithForce(force))
}
var _ = Describe("Repository", func() {
Context("Generation", func() {
ctx := types.NewContext()
ctx := context.NewContext()
It("Generate repository metadata", func() {
tmpdir, err := ioutil.TempDir("", "tree")
@ -139,11 +140,11 @@ var _ = Describe("Repository", func() {
Expect(len(generalRecipe2.GetDatabase().GetPackages())).To(Equal(1))
Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(3))
compiler2 := compiler.NewLuetCompiler(backend.NewSimpleDockerBackend(ctx), generalRecipe2.GetDatabase(), options.WithContext(types.NewContext()))
compiler2 := compiler.NewLuetCompiler(backend.NewSimpleDockerBackend(ctx), generalRecipe2.GetDatabase(), options.WithContext(context.NewContext()))
spec2, err := compiler2.FromPackage(&pkg.DefaultPackage{Name: "alpine", Category: "seed", Version: "1.0"})
Expect(err).ToNot(HaveOccurred())
compiler := compiler.NewLuetCompiler(backend.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase(), options.WithContext(types.NewContext()))
compiler := compiler.NewLuetCompiler(backend.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase(), options.WithContext(context.NewContext()))
spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"})
Expect(err).ToNot(HaveOccurred())
@ -466,12 +467,12 @@ urls:
})
Context("Docker repository", func() {
repoImage := os.Getenv("UNIT_TEST_DOCKER_IMAGE_REPOSITORY")
ctx := types.NewContext()
ctx := context.NewContext()
BeforeEach(func() {
if repoImage == "" {
Skip("UNIT_TEST_DOCKER_IMAGE_REPOSITORY not specified")
}
ctx = types.NewContext()
ctx = context.NewContext()
})
It("generates images", func() {

View File

@ -40,7 +40,7 @@ func (s *System) OSCheck() (notFound pkg.Packages) {
return
}
func (s *System) ExecuteFinalizers(ctx *types.Context, packs []pkg.Package) error {
func (s *System) ExecuteFinalizers(ctx types.Context, packs []pkg.Package) error {
var errs error
executedFinalizer := map[string]bool{}
for _, p := range packs {

21
vendor/github.com/ipfs/go-log/v2/LICENSE generated vendored Normal file
View File

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2014 Juan Batiz-Benet
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

137
vendor/github.com/ipfs/go-log/v2/README.md generated vendored Normal file
View File

@ -0,0 +1,137 @@
# go-log
[![](https://img.shields.io/badge/made%20by-Protocol%20Labs-blue.svg?style=flat-square)](https://protocol.ai)
[![](https://img.shields.io/badge/project-IPFS-blue.svg?style=flat-square)](https://ipfs.io/)
[![GoDoc](https://pkg.go.dev/badge/github.com/ipfs/go-log/v2.svg)](https://pkg.go.dev/github.com/ipfs/go-log/v2)
> The logging library used by go-ipfs
go-log wraps [zap](https://github.com/uber-go/zap) to provide a logging facade. go-log manages logging
instances and allows for their levels to be controlled individually.
## Install
```sh
go get github.com/ipfs/go-log
```
## Usage
Once the package is imported under the name `logging`, an instance of `EventLogger` can be created like so:
```go
var log = logging.Logger("subsystem name")
```
It can then be used to emit log messages in plain printf-style messages at seven standard levels:
Levels may be set for all loggers:
```go
lvl, err := logging.LevelFromString("error")
if err != nil {
panic(err)
}
logging.SetAllLoggers(lvl)
```
or individually:
```go
err := logging.SetLogLevel("net:pubsub", "info")
if err != nil {
panic(err)
}
```
or by regular expression:
```go
err := logging.SetLogLevelRegex("net:.*", "info")
if err != nil {
panic(err)
}
```
### Environment Variables
This package can be configured through various environment variables.
#### `GOLOG_LOG_LEVEL`
Specifies the log-level, both globally and on a per-subsystem basis.
For example, the following will set the global minimum log level to `error`, but reduce the minimum
log level for `subsystem1` to `info` and reduce the minimum log level for `subsystem2` to debug.
```bash
export GOLOG_LOG_LEVEL="error,subsystem1=info,subsystem2=debug"
```
`IPFS_LOGGING` is a deprecated alias for this environment variable.
#### `GOLOG_FILE`
Specifies that logs should be written to the specified file. If this option is _not_ specified, logs are written to standard error.
```bash
export GOLOG_FILE="/path/to/my/file.log"
```
#### `GOLOG_OUTPUT`
Specifies where logging output should be written. Can take one or more of the following values, combined with `+`:
- `stdout` -- write logs to standard out.
- `stderr` -- write logs to standard error.
- `file` -- write logs to the file specified by `GOLOG_FILE`
For example, if you want to log to both a file and standard error:
```bash
export GOLOG_FILE="/path/to/my/file.log"
export GOLOG_OUTPUT="stderr+file"
```
Setting _only_ `GOLOG_FILE` will prevent logs from being written to standard error.
#### `GOLOG_LOG_FMT`
Specifies the log message format. It supports the following values:
- `color` -- human readable, colorized (ANSI) output
- `nocolor` -- human readable, plain-text output.
- `json` -- structured JSON.
For example, to log structured JSON (for easier parsing):
```bash
export GOLOG_LOG_FMT="json"
```
The logging format defaults to `color` when the output is a terminal, and `nocolor` otherwise.
`IPFS_LOGGING_FMT` is a deprecated alias for this environment variable.
#### `GOLOG_LOG_LABELS`
Specifies a set of labels that should be added to all log messages as comma-separated key-value
pairs. For example, the following add `{"app": "example_app", "dc": "sjc-1"}` to every log entry.
```bash
export GOLOG_LOG_LABELS="app=example_app,dc=sjc-1"
```
## Contribute
Feel free to join in. All welcome. Open an [issue](https://github.com/ipfs/go-log/issues)!
This repository falls under the IPFS [Code of Conduct](https://github.com/ipfs/community/blob/master/code-of-conduct.md).
### Want to hack on IPFS?
[![](https://cdn.rawgit.com/jbenet/contribute-ipfs-gif/master/img/contribute.gif)](https://github.com/ipfs/community/blob/master/CONTRIBUTING.md)
## License
MIT

121
vendor/github.com/ipfs/go-log/v2/core.go generated vendored Normal file
View File

@ -0,0 +1,121 @@
package log
import (
"reflect"
"sync"
"go.uber.org/multierr"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
)
var _ zapcore.Core = (*lockedMultiCore)(nil)
type lockedMultiCore struct {
mu sync.RWMutex // guards mutations to cores slice
cores []zapcore.Core
}
func (l *lockedMultiCore) With(fields []zapcore.Field) zapcore.Core {
l.mu.RLock()
defer l.mu.RUnlock()
sub := &lockedMultiCore{
cores: make([]zapcore.Core, len(l.cores)),
}
for i := range l.cores {
sub.cores[i] = l.cores[i].With(fields)
}
return sub
}
func (l *lockedMultiCore) Enabled(lvl zapcore.Level) bool {
l.mu.RLock()
defer l.mu.RUnlock()
for i := range l.cores {
if l.cores[i].Enabled(lvl) {
return true
}
}
return false
}
func (l *lockedMultiCore) Check(ent zapcore.Entry, ce *zapcore.CheckedEntry) *zapcore.CheckedEntry {
l.mu.RLock()
defer l.mu.RUnlock()
for i := range l.cores {
ce = l.cores[i].Check(ent, ce)
}
return ce
}
func (l *lockedMultiCore) Write(ent zapcore.Entry, fields []zapcore.Field) error {
l.mu.RLock()
defer l.mu.RUnlock()
var err error
for i := range l.cores {
err = multierr.Append(err, l.cores[i].Write(ent, fields))
}
return err
}
func (l *lockedMultiCore) Sync() error {
l.mu.RLock()
defer l.mu.RUnlock()
var err error
for i := range l.cores {
err = multierr.Append(err, l.cores[i].Sync())
}
return err
}
func (l *lockedMultiCore) AddCore(core zapcore.Core) {
l.mu.Lock()
defer l.mu.Unlock()
l.cores = append(l.cores, core)
}
func (l *lockedMultiCore) DeleteCore(core zapcore.Core) {
l.mu.Lock()
defer l.mu.Unlock()
w := 0
for i := 0; i < len(l.cores); i++ {
if reflect.DeepEqual(l.cores[i], core) {
continue
}
l.cores[w] = l.cores[i]
w++
}
l.cores = l.cores[:w]
}
func (l *lockedMultiCore) ReplaceCore(original, replacement zapcore.Core) {
l.mu.Lock()
defer l.mu.Unlock()
for i := 0; i < len(l.cores); i++ {
if reflect.DeepEqual(l.cores[i], original) {
l.cores[i] = replacement
}
}
}
func newCore(format LogFormat, ws zapcore.WriteSyncer, level LogLevel) zapcore.Core {
encCfg := zap.NewProductionEncoderConfig()
encCfg.EncodeTime = zapcore.ISO8601TimeEncoder
var encoder zapcore.Encoder
switch format {
case PlaintextOutput:
encCfg.EncodeLevel = zapcore.CapitalLevelEncoder
encoder = zapcore.NewConsoleEncoder(encCfg)
case JSONOutput:
encoder = zapcore.NewJSONEncoder(encCfg)
default:
encCfg.EncodeLevel = zapcore.CapitalColorLevelEncoder
encoder = zapcore.NewConsoleEncoder(encCfg)
}
return zapcore.NewCore(encoder, ws, zap.NewAtomicLevelAt(zapcore.Level(level)))
}

9
vendor/github.com/ipfs/go-log/v2/go.mod generated vendored Normal file
View File

@ -0,0 +1,9 @@
module github.com/ipfs/go-log/v2
require (
github.com/mattn/go-isatty v0.0.14
go.uber.org/multierr v1.6.0
go.uber.org/zap v1.16.0
)
go 1.16

57
vendor/github.com/ipfs/go-log/v2/go.sum generated vendored Normal file
View File

@ -0,0 +1,57 @@
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU=
go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4=
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
go.uber.org/zap v1.16.0 h1:uFRZXykJGK9lLY4HtgSw44DnIcAM+kRBP7x5m+NpAOM=
go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c h1:F1jZWGFhYfh0Ci55sIpILtKKK8p3i2/krTr0H1rg74I=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5 h1:hKsoRgsbwY1NafxrwTs+k64bikrLBkAgPir1TNCj3Zs=
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM=
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=

30
vendor/github.com/ipfs/go-log/v2/levels.go generated vendored Normal file
View File

@ -0,0 +1,30 @@
package log
import "go.uber.org/zap/zapcore"
// LogLevel represents a log severity level. Use the package variables as an
// enum.
type LogLevel zapcore.Level
var (
LevelDebug = LogLevel(zapcore.DebugLevel)
LevelInfo = LogLevel(zapcore.InfoLevel)
LevelWarn = LogLevel(zapcore.WarnLevel)
LevelError = LogLevel(zapcore.ErrorLevel)
LevelDPanic = LogLevel(zapcore.DPanicLevel)
LevelPanic = LogLevel(zapcore.PanicLevel)
LevelFatal = LogLevel(zapcore.FatalLevel)
)
// LevelFromString parses a string-based level and returns the corresponding
// LogLevel.
//
// Supported strings are: DEBUG, INFO, WARN, ERROR, DPANIC, PANIC, FATAL, and
// their lower-case forms.
//
// The returned LogLevel must be discarded if error is not nil.
func LevelFromString(level string) (LogLevel, error) {
lvl := zapcore.InfoLevel // zero value
err := lvl.Set(level)
return LogLevel(lvl), err
}

84
vendor/github.com/ipfs/go-log/v2/log.go generated vendored Normal file
View File

@ -0,0 +1,84 @@
// Package log is the logging library used by IPFS & libp2p
// (https://github.com/ipfs/go-ipfs).
package log
import (
"time"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
)
// StandardLogger provides API compatibility with standard printf loggers
// eg. go-logging
type StandardLogger interface {
Debug(args ...interface{})
Debugf(format string, args ...interface{})
Error(args ...interface{})
Errorf(format string, args ...interface{})
Fatal(args ...interface{})
Fatalf(format string, args ...interface{})
Info(args ...interface{})
Infof(format string, args ...interface{})
Panic(args ...interface{})
Panicf(format string, args ...interface{})
Warn(args ...interface{})
Warnf(format string, args ...interface{})
}
// EventLogger extends the StandardLogger interface to allow for log items
// containing structured metadata
type EventLogger interface {
StandardLogger
}
// Logger retrieves an event logger by name
func Logger(system string) *ZapEventLogger {
if len(system) == 0 {
setuplog := getLogger("setup-logger")
setuplog.Error("Missing name parameter")
system = "undefined"
}
logger := getLogger(system)
skipLogger := logger.Desugar().WithOptions(zap.AddCallerSkip(1)).Sugar()
return &ZapEventLogger{
system: system,
SugaredLogger: *logger,
skipLogger: *skipLogger,
}
}
// ZapEventLogger implements the EventLogger and wraps a go-logging Logger
type ZapEventLogger struct {
zap.SugaredLogger
// used to fix the caller location when calling Warning and Warningf.
skipLogger zap.SugaredLogger
system string
}
// Warning is for compatibility
// Deprecated: use Warn(args ...interface{}) instead
func (logger *ZapEventLogger) Warning(args ...interface{}) {
logger.skipLogger.Warn(args...)
}
// Warningf is for compatibility
// Deprecated: use Warnf(format string, args ...interface{}) instead
func (logger *ZapEventLogger) Warningf(format string, args ...interface{}) {
logger.skipLogger.Warnf(format, args...)
}
// FormatRFC3339 returns the given time in UTC with RFC3999Nano format.
func FormatRFC3339(t time.Time) string {
return t.UTC().Format(time.RFC3339Nano)
}
func WithStacktrace(l *ZapEventLogger, level LogLevel) *ZapEventLogger {
copyLogger := *l
copyLogger.SugaredLogger = *copyLogger.SugaredLogger.Desugar().
WithOptions(zap.AddStacktrace(zapcore.Level(level))).Sugar()
copyLogger.skipLogger = *copyLogger.SugaredLogger.Desugar().WithOptions(zap.AddCallerSkip(1)).Sugar()
return &copyLogger
}

12
vendor/github.com/ipfs/go-log/v2/path_other.go generated vendored Normal file
View File

@ -0,0 +1,12 @@
//go:build !windows
// +build !windows
package log
import (
"path/filepath"
)
func normalizePath(p string) (string, error) {
return filepath.Abs(p)
}

36
vendor/github.com/ipfs/go-log/v2/path_windows.go generated vendored Normal file
View File

@ -0,0 +1,36 @@
//go:build windows
// +build windows
package log
import (
"fmt"
"path/filepath"
"strings"
)
func normalizePath(p string) (string, error) {
if p == "" {
return "", fmt.Errorf("path empty")
}
p, err := filepath.Abs(p)
if err != nil {
return "", err
}
// Is this _really_ an absolute path?
if !strings.HasPrefix(p, "\\\\") {
// It's a drive: path!
// Return a UNC path.
p = "\\\\%3F\\" + p
}
// This will return file:////?/c:/foobar
//
// Why? Because:
// 1. Go will choke on file://c:/ because the "domain" includes a :.
// 2. Windows will choke on file:///c:/ because the path will be
// /c:/... which is _relative_ to the current drive.
//
// This path (a) has no "domain" and (b) starts with a slash. Yay!
return "file://" + filepath.ToSlash(p), nil
}

90
vendor/github.com/ipfs/go-log/v2/pipe.go generated vendored Normal file
View File

@ -0,0 +1,90 @@
package log
import (
"io"
"go.uber.org/multierr"
"go.uber.org/zap/zapcore"
)
// A PipeReader is a reader that reads from the logger. It is synchronous
// so blocking on read will affect logging performance.
type PipeReader struct {
r *io.PipeReader
closer io.Closer
core zapcore.Core
}
// Read implements the standard Read interface
func (p *PipeReader) Read(data []byte) (int, error) {
return p.r.Read(data)
}
// Close unregisters the reader from the logger.
func (p *PipeReader) Close() error {
if p.core != nil {
loggerCore.DeleteCore(p.core)
}
return multierr.Append(p.core.Sync(), p.closer.Close())
}
// NewPipeReader creates a new in-memory reader that reads from all loggers
// The caller must call Close on the returned reader when done.
//
// By default, it:
//
// 1. Logs JSON. This can be changed by passing the PipeFormat option.
// 2. Logs everything that would otherwise be logged to the "primary" log
// output. That is, everything enabled by SetLogLevel. The minimum log level
// can be increased by passing the PipeLevel option.
func NewPipeReader(opts ...PipeReaderOption) *PipeReader {
opt := pipeReaderOptions{
format: JSONOutput,
level: LevelDebug,
}
for _, o := range opts {
o.setOption(&opt)
}
r, w := io.Pipe()
p := &PipeReader{
r: r,
closer: w,
core: newCore(opt.format, zapcore.AddSync(w), opt.level),
}
loggerCore.AddCore(p.core)
return p
}
type pipeReaderOptions struct {
format LogFormat
level LogLevel
}
type PipeReaderOption interface {
setOption(*pipeReaderOptions)
}
type pipeReaderOptionFunc func(*pipeReaderOptions)
func (p pipeReaderOptionFunc) setOption(o *pipeReaderOptions) {
p(o)
}
// PipeFormat sets the output format of the pipe reader
func PipeFormat(format LogFormat) PipeReaderOption {
return pipeReaderOptionFunc(func(o *pipeReaderOptions) {
o.format = format
})
}
// PipeLevel sets the log level of logs sent to the pipe reader.
func PipeLevel(level LogLevel) PipeReaderOption {
return pipeReaderOptionFunc(func(o *pipeReaderOptions) {
o.level = level
})
}

390
vendor/github.com/ipfs/go-log/v2/setup.go generated vendored Normal file
View File

@ -0,0 +1,390 @@
package log
import (
"errors"
"fmt"
"os"
"regexp"
"strings"
"sync"
"github.com/mattn/go-isatty"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
)
func init() {
SetupLogging(configFromEnv())
}
// Logging environment variables
const (
// IPFS_* prefixed env vars kept for backwards compatibility
// for this release. They will not be available in the next
// release.
//
// GOLOG_* env vars take precedences over IPFS_* env vars.
envIPFSLogging = "IPFS_LOGGING"
envIPFSLoggingFmt = "IPFS_LOGGING_FMT"
envLogging = "GOLOG_LOG_LEVEL"
envLoggingFmt = "GOLOG_LOG_FMT"
envLoggingFile = "GOLOG_FILE" // /path/to/file
envLoggingURL = "GOLOG_URL" // url that will be processed by sink in the zap
envLoggingOutput = "GOLOG_OUTPUT" // possible values: stdout|stderr|file combine multiple values with '+'
envLoggingLabels = "GOLOG_LOG_LABELS" // comma-separated key-value pairs, i.e. "app=example_app,dc=sjc-1"
)
type LogFormat int
const (
ColorizedOutput LogFormat = iota
PlaintextOutput
JSONOutput
)
type Config struct {
// Format overrides the format of the log output. Defaults to ColorizedOutput
Format LogFormat
// Level is the default minimum enabled logging level.
Level LogLevel
// SubsystemLevels are the default levels per-subsystem. When unspecified, defaults to Level.
SubsystemLevels map[string]LogLevel
// Stderr indicates whether logs should be written to stderr.
Stderr bool
// Stdout indicates whether logs should be written to stdout.
Stdout bool
// File is a path to a file that logs will be written to.
File string
// URL with schema supported by zap. Use zap.RegisterSink
URL string
// Labels is a set of key-values to apply to all loggers
Labels map[string]string
}
// ErrNoSuchLogger is returned when the util pkg is asked for a non existant logger
var ErrNoSuchLogger = errors.New("error: No such logger")
var loggerMutex sync.RWMutex // guards access to global logger state
// loggers is the set of loggers in the system
var loggers = make(map[string]*zap.SugaredLogger)
var levels = make(map[string]zap.AtomicLevel)
// primaryFormat is the format of the primary core used for logging
var primaryFormat LogFormat = ColorizedOutput
// defaultLevel is the default log level
var defaultLevel LogLevel = LevelError
// primaryCore is the primary logging core
var primaryCore zapcore.Core
// loggerCore is the base for all loggers created by this package
var loggerCore = &lockedMultiCore{}
// SetupLogging will initialize the logger backend and set the flags.
// TODO calling this in `init` pushes all configuration to env variables
// - move it out of `init`? then we need to change all the code (js-ipfs, go-ipfs) to call this explicitly
// - have it look for a config file? need to define what that is
func SetupLogging(cfg Config) {
loggerMutex.Lock()
defer loggerMutex.Unlock()
primaryFormat = cfg.Format
defaultLevel = cfg.Level
outputPaths := []string{}
if cfg.Stderr {
outputPaths = append(outputPaths, "stderr")
}
if cfg.Stdout {
outputPaths = append(outputPaths, "stdout")
}
// check if we log to a file
if len(cfg.File) > 0 {
if path, err := normalizePath(cfg.File); err != nil {
fmt.Fprintf(os.Stderr, "failed to resolve log path '%q', logging to %s\n", cfg.File, outputPaths)
} else {
outputPaths = append(outputPaths, path)
}
}
if len(cfg.URL) > 0 {
outputPaths = append(outputPaths, cfg.URL)
}
ws, _, err := zap.Open(outputPaths...)
if err != nil {
panic(fmt.Sprintf("unable to open logging output: %v", err))
}
newPrimaryCore := newCore(primaryFormat, ws, LevelDebug) // the main core needs to log everything.
for k, v := range cfg.Labels {
newPrimaryCore = newPrimaryCore.With([]zap.Field{zap.String(k, v)})
}
setPrimaryCore(newPrimaryCore)
setAllLoggers(defaultLevel)
for name, level := range cfg.SubsystemLevels {
if leveler, ok := levels[name]; ok {
leveler.SetLevel(zapcore.Level(level))
} else {
levels[name] = zap.NewAtomicLevelAt(zapcore.Level(level))
}
}
}
// SetPrimaryCore changes the primary logging core. If the SetupLogging was
// called then the previously configured core will be replaced.
func SetPrimaryCore(core zapcore.Core) {
loggerMutex.Lock()
defer loggerMutex.Unlock()
setPrimaryCore(core)
}
func setPrimaryCore(core zapcore.Core) {
if primaryCore != nil {
loggerCore.ReplaceCore(primaryCore, core)
} else {
loggerCore.AddCore(core)
}
primaryCore = core
}
// SetDebugLogging calls SetAllLoggers with logging.DEBUG
func SetDebugLogging() {
SetAllLoggers(LevelDebug)
}
// SetAllLoggers changes the logging level of all loggers to lvl
func SetAllLoggers(lvl LogLevel) {
loggerMutex.RLock()
defer loggerMutex.RUnlock()
setAllLoggers(lvl)
}
func setAllLoggers(lvl LogLevel) {
for _, l := range levels {
l.SetLevel(zapcore.Level(lvl))
}
}
// SetLogLevel changes the log level of a specific subsystem
// name=="*" changes all subsystems
func SetLogLevel(name, level string) error {
lvl, err := LevelFromString(level)
if err != nil {
return err
}
// wildcard, change all
if name == "*" {
SetAllLoggers(lvl)
return nil
}
loggerMutex.RLock()
defer loggerMutex.RUnlock()
// Check if we have a logger by that name
if _, ok := levels[name]; !ok {
return ErrNoSuchLogger
}
levels[name].SetLevel(zapcore.Level(lvl))
return nil
}
// SetLogLevelRegex sets all loggers to level `l` that match expression `e`.
// An error is returned if `e` fails to compile.
func SetLogLevelRegex(e, l string) error {
lvl, err := LevelFromString(l)
if err != nil {
return err
}
rem, err := regexp.Compile(e)
if err != nil {
return err
}
loggerMutex.Lock()
defer loggerMutex.Unlock()
for name := range loggers {
if rem.MatchString(name) {
levels[name].SetLevel(zapcore.Level(lvl))
}
}
return nil
}
// GetSubsystems returns a slice containing the
// names of the current loggers
func GetSubsystems() []string {
loggerMutex.RLock()
defer loggerMutex.RUnlock()
subs := make([]string, 0, len(loggers))
for k := range loggers {
subs = append(subs, k)
}
return subs
}
func getLogger(name string) *zap.SugaredLogger {
loggerMutex.Lock()
defer loggerMutex.Unlock()
log, ok := loggers[name]
if !ok {
level, ok := levels[name]
if !ok {
level = zap.NewAtomicLevelAt(zapcore.Level(defaultLevel))
levels[name] = level
}
log = zap.New(loggerCore).
WithOptions(
zap.IncreaseLevel(level),
zap.AddCaller(),
).
Named(name).
Sugar()
loggers[name] = log
}
return log
}
// configFromEnv returns a Config with defaults populated using environment variables.
func configFromEnv() Config {
cfg := Config{
Format: ColorizedOutput,
Stderr: true,
Level: LevelError,
SubsystemLevels: map[string]LogLevel{},
Labels: map[string]string{},
}
format := os.Getenv(envLoggingFmt)
if format == "" {
format = os.Getenv(envIPFSLoggingFmt)
}
var noExplicitFormat bool
switch format {
case "color":
cfg.Format = ColorizedOutput
case "nocolor":
cfg.Format = PlaintextOutput
case "json":
cfg.Format = JSONOutput
default:
if format != "" {
fmt.Fprintf(os.Stderr, "ignoring unrecognized log format '%s'\n", format)
}
noExplicitFormat = true
}
lvl := os.Getenv(envLogging)
if lvl == "" {
lvl = os.Getenv(envIPFSLogging)
}
if lvl != "" {
for _, kvs := range strings.Split(lvl, ",") {
kv := strings.SplitN(kvs, "=", 2)
lvl, err := LevelFromString(kv[len(kv)-1])
if err != nil {
fmt.Fprintf(os.Stderr, "error setting log level %q: %s\n", kvs, err)
continue
}
switch len(kv) {
case 1:
cfg.Level = lvl
case 2:
cfg.SubsystemLevels[kv[0]] = lvl
}
}
}
cfg.File = os.Getenv(envLoggingFile)
// Disable stderr logging when a file is specified
// https://github.com/ipfs/go-log/issues/83
if cfg.File != "" {
cfg.Stderr = false
}
cfg.URL = os.Getenv(envLoggingURL)
output := os.Getenv(envLoggingOutput)
outputOptions := strings.Split(output, "+")
for _, opt := range outputOptions {
switch opt {
case "stdout":
cfg.Stdout = true
case "stderr":
cfg.Stderr = true
case "file":
if cfg.File == "" {
fmt.Fprint(os.Stderr, "please specify a GOLOG_FILE value to write to")
}
case "url":
if cfg.URL == "" {
fmt.Fprint(os.Stderr, "please specify a GOLOG_URL value to write to")
}
}
}
// Check that neither of the requested Std* nor the file are TTYs
// At this stage (configFromEnv) we do not have a uniform list to examine yet
if noExplicitFormat &&
!(cfg.Stdout && isTerm(os.Stdout)) &&
!(cfg.Stderr && isTerm(os.Stderr)) &&
// check this last: expensive
!(cfg.File != "" && pathIsTerm(cfg.File)) {
cfg.Format = PlaintextOutput
}
labels := os.Getenv(envLoggingLabels)
if labels != "" {
labelKVs := strings.Split(labels, ",")
for _, label := range labelKVs {
kv := strings.Split(label, "=")
if len(kv) != 2 {
fmt.Fprint(os.Stderr, "invalid label k=v: ", label)
continue
}
cfg.Labels[kv[0]] = kv[1]
}
}
return cfg
}
func isTerm(f *os.File) bool {
return isatty.IsTerminal(f.Fd()) || isatty.IsCygwinTerminal(f.Fd())
}
func pathIsTerm(p string) bool {
// !!!no!!! O_CREAT, if we fail - we fail
f, err := os.OpenFile(p, os.O_WRONLY, 0)
if f != nil {
defer f.Close() // nolint:errcheck
}
return err == nil && isTerm(f)
}

3
vendor/github.com/ipfs/go-log/v2/version.json generated vendored Normal file
View File

@ -0,0 +1,3 @@
{
"version": "v2.4.0"
}

9
vendor/github.com/mattn/go-isatty/LICENSE generated vendored Normal file
View File

@ -0,0 +1,9 @@
Copyright (c) Yasuhiro MATSUMOTO <mattn.jp@gmail.com>
MIT License (Expat)
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

50
vendor/github.com/mattn/go-isatty/README.md generated vendored Normal file
View File

@ -0,0 +1,50 @@
# go-isatty
[![Godoc Reference](https://godoc.org/github.com/mattn/go-isatty?status.svg)](http://godoc.org/github.com/mattn/go-isatty)
[![Codecov](https://codecov.io/gh/mattn/go-isatty/branch/master/graph/badge.svg)](https://codecov.io/gh/mattn/go-isatty)
[![Coverage Status](https://coveralls.io/repos/github/mattn/go-isatty/badge.svg?branch=master)](https://coveralls.io/github/mattn/go-isatty?branch=master)
[![Go Report Card](https://goreportcard.com/badge/mattn/go-isatty)](https://goreportcard.com/report/mattn/go-isatty)
isatty for golang
## Usage
```go
package main
import (
"fmt"
"github.com/mattn/go-isatty"
"os"
)
func main() {
if isatty.IsTerminal(os.Stdout.Fd()) {
fmt.Println("Is Terminal")
} else if isatty.IsCygwinTerminal(os.Stdout.Fd()) {
fmt.Println("Is Cygwin/MSYS2 Terminal")
} else {
fmt.Println("Is Not Terminal")
}
}
```
## Installation
```
$ go get github.com/mattn/go-isatty
```
## License
MIT
## Author
Yasuhiro Matsumoto (a.k.a mattn)
## Thanks
* k-takata: base idea for IsCygwinTerminal
https://github.com/k-takata/go-iscygpty

2
vendor/github.com/mattn/go-isatty/doc.go generated vendored Normal file
View File

@ -0,0 +1,2 @@
// Package isatty implements interface to isatty
package isatty

5
vendor/github.com/mattn/go-isatty/go.mod generated vendored Normal file
View File

@ -0,0 +1,5 @@
module github.com/mattn/go-isatty
go 1.12
require golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c

2
vendor/github.com/mattn/go-isatty/go.sum generated vendored Normal file
View File

@ -0,0 +1,2 @@
golang.org/x/sys v0.0.0-20200116001909-b77594299b42 h1:vEOn+mP2zCOVzKckCZy6YsCtDblrpj/w7B9nxGNELpg=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=

12
vendor/github.com/mattn/go-isatty/go.test.sh generated vendored Normal file
View File

@ -0,0 +1,12 @@
#!/usr/bin/env bash
set -e
echo "" > coverage.txt
for d in $(go list ./... | grep -v vendor); do
go test -race -coverprofile=profile.out -covermode=atomic "$d"
if [ -f profile.out ]; then
cat profile.out >> coverage.txt
rm profile.out
fi
done

19
vendor/github.com/mattn/go-isatty/isatty_bsd.go generated vendored Normal file
View File

@ -0,0 +1,19 @@
//go:build (darwin || freebsd || openbsd || netbsd || dragonfly) && !appengine
// +build darwin freebsd openbsd netbsd dragonfly
// +build !appengine
package isatty
import "golang.org/x/sys/unix"
// IsTerminal return true if the file descriptor is terminal.
func IsTerminal(fd uintptr) bool {
_, err := unix.IoctlGetTermios(int(fd), unix.TIOCGETA)
return err == nil
}
// IsCygwinTerminal return true if the file descriptor is a cygwin or msys2
// terminal. This is also always false on this environment.
func IsCygwinTerminal(fd uintptr) bool {
return false
}

16
vendor/github.com/mattn/go-isatty/isatty_others.go generated vendored Normal file
View File

@ -0,0 +1,16 @@
//go:build appengine || js || nacl || wasm
// +build appengine js nacl wasm
package isatty
// IsTerminal returns true if the file descriptor is terminal which
// is always false on js and appengine classic which is a sandboxed PaaS.
func IsTerminal(fd uintptr) bool {
return false
}
// IsCygwinTerminal() return true if the file descriptor is a cygwin or msys2
// terminal. This is also always false on this environment.
func IsCygwinTerminal(fd uintptr) bool {
return false
}

Some files were not shown because too many files have changed in this diff Show More