mirror of
https://github.com/mudler/luet.git
synced 2025-08-02 07:59:22 +00:00
🎨 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:
parent
fd90e0d627
commit
c98f427156
23
cmd/build.go
23
cmd/build.go
@ -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")
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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")
|
||||
|
||||
|
@ -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")
|
||||
|
||||
|
@ -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")
|
||||
|
@ -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)
|
||||
|
@ -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")
|
||||
|
@ -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")
|
||||
|
@ -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)
|
||||
|
20
cmd/root.go
20
cmd/root.go
@ -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)
|
||||
}
|
||||
|
@ -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")
|
||||
|
@ -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,
|
||||
|
@ -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 {
|
||||
|
@ -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")
|
||||
|
@ -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)")
|
||||
|
@ -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)")
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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
4
go.mod
@ -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
7
go.sum
@ -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=
|
||||
|
@ -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 {
|
||||
|
@ -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",
|
||||
|
28
pkg/api/core/context/contest_suite_test.go
Normal file
28
pkg/api/core/context/contest_suite_test.go
Normal 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")
|
||||
}
|
159
pkg/api/core/context/context.go
Normal file
159
pkg/api/core/context/context.go
Normal 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
|
||||
}
|
59
pkg/api/core/garbagecollector/garbagecollector.go
Normal file
59
pkg/api/core/garbagecollector/garbagecollector.go
Normal 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)
|
||||
}
|
@ -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.
|
||||
})
|
||||
|
@ -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())
|
||||
|
||||
|
@ -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())
|
||||
|
@ -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...)
|
||||
}
|
||||
|
@ -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())
|
||||
|
@ -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"})
|
||||
|
||||
|
28
pkg/api/core/logger/config_suite_test.go
Normal file
28
pkg/api/core/logger/config_suite_test.go
Normal 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")
|
||||
}
|
367
pkg/api/core/logger/logger.go
Normal file
367
pkg/api/core/logger/logger.go
Normal 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()
|
||||
}
|
||||
}
|
@ -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"))
|
43
pkg/api/core/logger/terminal.go
Normal file
43
pkg/api/core/logger/terminal.go
Normal 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
|
||||
}
|
@ -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")
|
||||
|
@ -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")
|
||||
|
@ -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())
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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())
|
||||
|
@ -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
|
||||
}
|
||||
|
25
pkg/api/core/types/garbagecollector.go
Normal file
25
pkg/api/core/types/garbagecollector.go
Normal 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
|
||||
}
|
41
pkg/api/core/types/logger.go
Normal file
41
pkg/api/core/types/logger.go
Normal 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)
|
||||
}
|
@ -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 {
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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))
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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")
|
||||
}
|
||||
|
@ -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())
|
||||
|
@ -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())
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
// +build js nacl plan9
|
||||
|
||||
package terminal
|
||||
|
||||
import (
|
||||
"io"
|
||||
)
|
||||
|
||||
func IsTerminal(w io.Writer) bool {
|
||||
return false
|
||||
}
|
@ -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
|
||||
}
|
@ -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
|
||||
}
|
@ -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
|
||||
}
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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()
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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")
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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() {
|
||||
|
@ -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")
|
||||
}
|
||||
|
@ -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")
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
|
@ -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() {
|
||||
|
@ -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
21
vendor/github.com/ipfs/go-log/v2/LICENSE
generated
vendored
Normal 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
137
vendor/github.com/ipfs/go-log/v2/README.md
generated
vendored
Normal file
@ -0,0 +1,137 @@
|
||||
# go-log
|
||||
|
||||
[](https://protocol.ai)
|
||||
[](https://ipfs.io/)
|
||||
[](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://github.com/ipfs/community/blob/master/CONTRIBUTING.md)
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
121
vendor/github.com/ipfs/go-log/v2/core.go
generated
vendored
Normal file
121
vendor/github.com/ipfs/go-log/v2/core.go
generated
vendored
Normal 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
9
vendor/github.com/ipfs/go-log/v2/go.mod
generated
vendored
Normal 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
57
vendor/github.com/ipfs/go-log/v2/go.sum
generated
vendored
Normal 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
30
vendor/github.com/ipfs/go-log/v2/levels.go
generated
vendored
Normal 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
84
vendor/github.com/ipfs/go-log/v2/log.go
generated
vendored
Normal 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 ©Logger
|
||||
}
|
12
vendor/github.com/ipfs/go-log/v2/path_other.go
generated
vendored
Normal file
12
vendor/github.com/ipfs/go-log/v2/path_other.go
generated
vendored
Normal 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
36
vendor/github.com/ipfs/go-log/v2/path_windows.go
generated
vendored
Normal 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
90
vendor/github.com/ipfs/go-log/v2/pipe.go
generated
vendored
Normal 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
390
vendor/github.com/ipfs/go-log/v2/setup.go
generated
vendored
Normal 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
3
vendor/github.com/ipfs/go-log/v2/version.json
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"version": "v2.4.0"
|
||||
}
|
9
vendor/github.com/mattn/go-isatty/LICENSE
generated
vendored
Normal file
9
vendor/github.com/mattn/go-isatty/LICENSE
generated
vendored
Normal 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
50
vendor/github.com/mattn/go-isatty/README.md
generated
vendored
Normal file
@ -0,0 +1,50 @@
|
||||
# go-isatty
|
||||
|
||||
[](http://godoc.org/github.com/mattn/go-isatty)
|
||||
[](https://codecov.io/gh/mattn/go-isatty)
|
||||
[](https://coveralls.io/github/mattn/go-isatty?branch=master)
|
||||
[](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
2
vendor/github.com/mattn/go-isatty/doc.go
generated
vendored
Normal 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
5
vendor/github.com/mattn/go-isatty/go.mod
generated
vendored
Normal 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
2
vendor/github.com/mattn/go-isatty/go.sum
generated
vendored
Normal 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
12
vendor/github.com/mattn/go-isatty/go.test.sh
generated
vendored
Normal 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
19
vendor/github.com/mattn/go-isatty/isatty_bsd.go
generated
vendored
Normal 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
16
vendor/github.com/mattn/go-isatty/isatty_others.go
generated
vendored
Normal 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
Loading…
Reference in New Issue
Block a user