Massive UX rewrite

- Ditch multiple libraries for progressbar, spinner, colors and replace
  with pterm
- Detect when running on terminal and disable automatically spinner
- Add support for multiple progress bars
- Huge rewrite of the configuration part. No more crazy stuff with viper
  CLI commands now correctly overrides default config file as expected
- Limit banner to be displayed on relevant parts

Fixes #211
Fixes #105
Fixes #247
Fixes #233
This commit is contained in:
Ettore Di Giacinto 2021-10-19 22:26:23 +02:00
parent d4edaa9de8
commit fe14d56afe
45 changed files with 730 additions and 463 deletions

View File

@ -36,6 +36,7 @@ import (
tree "github.com/mudler/luet/pkg/tree" tree "github.com/mudler/luet/pkg/tree"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/viper"
) )
var buildCmd = &cobra.Command{ var buildCmd = &cobra.Command{
@ -65,54 +66,54 @@ Build packages specifying multiple definition trees:
$ luet build --tree overlay/path --tree overlay/path2 utils/yq ... $ luet build --tree overlay/path --tree overlay/path2 utils/yq ...
`, PreRun: func(cmd *cobra.Command, args []string) { `, PreRun: func(cmd *cobra.Command, args []string) {
LuetCfg.Viper.BindPFlag("tree", cmd.Flags().Lookup("tree")) viper.BindPFlag("tree", cmd.Flags().Lookup("tree"))
LuetCfg.Viper.BindPFlag("destination", cmd.Flags().Lookup("destination")) viper.BindPFlag("destination", cmd.Flags().Lookup("destination"))
LuetCfg.Viper.BindPFlag("backend", cmd.Flags().Lookup("backend")) viper.BindPFlag("backend", cmd.Flags().Lookup("backend"))
LuetCfg.Viper.BindPFlag("privileged", cmd.Flags().Lookup("privileged")) viper.BindPFlag("privileged", cmd.Flags().Lookup("privileged"))
LuetCfg.Viper.BindPFlag("revdeps", cmd.Flags().Lookup("revdeps")) viper.BindPFlag("revdeps", cmd.Flags().Lookup("revdeps"))
LuetCfg.Viper.BindPFlag("all", cmd.Flags().Lookup("all")) viper.BindPFlag("all", cmd.Flags().Lookup("all"))
LuetCfg.Viper.BindPFlag("compression", cmd.Flags().Lookup("compression")) viper.BindPFlag("compression", cmd.Flags().Lookup("compression"))
LuetCfg.Viper.BindPFlag("nodeps", cmd.Flags().Lookup("nodeps")) viper.BindPFlag("nodeps", cmd.Flags().Lookup("nodeps"))
LuetCfg.Viper.BindPFlag("onlydeps", cmd.Flags().Lookup("onlydeps")) viper.BindPFlag("onlydeps", cmd.Flags().Lookup("onlydeps"))
util.BindValuesFlags(cmd) util.BindValuesFlags(cmd)
LuetCfg.Viper.BindPFlag("backend-args", cmd.Flags().Lookup("backend-args")) viper.BindPFlag("backend-args", cmd.Flags().Lookup("backend-args"))
LuetCfg.Viper.BindPFlag("image-repository", cmd.Flags().Lookup("image-repository")) viper.BindPFlag("image-repository", cmd.Flags().Lookup("image-repository"))
LuetCfg.Viper.BindPFlag("push", cmd.Flags().Lookup("push")) viper.BindPFlag("push", cmd.Flags().Lookup("push"))
LuetCfg.Viper.BindPFlag("pull", cmd.Flags().Lookup("pull")) viper.BindPFlag("pull", cmd.Flags().Lookup("pull"))
LuetCfg.Viper.BindPFlag("wait", cmd.Flags().Lookup("wait")) viper.BindPFlag("wait", cmd.Flags().Lookup("wait"))
LuetCfg.Viper.BindPFlag("keep-images", cmd.Flags().Lookup("keep-images")) viper.BindPFlag("keep-images", cmd.Flags().Lookup("keep-images"))
util.BindSolverFlags(cmd) util.BindSolverFlags(cmd)
LuetCfg.Viper.BindPFlag("general.show_build_output", cmd.Flags().Lookup("live-output")) viper.BindPFlag("general.show_build_output", cmd.Flags().Lookup("live-output"))
LuetCfg.Viper.BindPFlag("backend-args", cmd.Flags().Lookup("backend-args")) viper.BindPFlag("backend-args", cmd.Flags().Lookup("backend-args"))
}, },
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
treePaths := LuetCfg.Viper.GetStringSlice("tree") treePaths := viper.GetStringSlice("tree")
dst := LuetCfg.Viper.GetString("destination") dst := viper.GetString("destination")
concurrency := LuetCfg.GetGeneral().Concurrency concurrency := LuetCfg.GetGeneral().Concurrency
backendType := LuetCfg.Viper.GetString("backend") backendType := viper.GetString("backend")
privileged := LuetCfg.Viper.GetBool("privileged") privileged := viper.GetBool("privileged")
revdeps := LuetCfg.Viper.GetBool("revdeps") revdeps := viper.GetBool("revdeps")
all := LuetCfg.Viper.GetBool("all") all := viper.GetBool("all")
compressionType := LuetCfg.Viper.GetString("compression") compressionType := viper.GetString("compression")
imageRepository := LuetCfg.Viper.GetString("image-repository") imageRepository := viper.GetString("image-repository")
values := util.ValuesFlags() values := util.ValuesFlags()
wait := LuetCfg.Viper.GetBool("wait") wait := viper.GetBool("wait")
push := LuetCfg.Viper.GetBool("push") push := viper.GetBool("push")
pull := LuetCfg.Viper.GetBool("pull") pull := viper.GetBool("pull")
keepImages := LuetCfg.Viper.GetBool("keep-images") keepImages := viper.GetBool("keep-images")
nodeps := LuetCfg.Viper.GetBool("nodeps") nodeps := viper.GetBool("nodeps")
onlydeps := LuetCfg.Viper.GetBool("onlydeps") onlydeps := viper.GetBool("onlydeps")
onlyTarget, _ := cmd.Flags().GetBool("only-target-package") onlyTarget, _ := cmd.Flags().GetBool("only-target-package")
full, _ := cmd.Flags().GetBool("full") full, _ := cmd.Flags().GetBool("full")
rebuild, _ := cmd.Flags().GetBool("rebuild") rebuild, _ := cmd.Flags().GetBool("rebuild")
var results Results var results Results
backendArgs := LuetCfg.Viper.GetStringSlice("backend-args") backendArgs := viper.GetStringSlice("backend-args")
out, _ := cmd.Flags().GetString("output") out, _ := cmd.Flags().GetString("output")
if out != "terminal" { if out != "terminal" {
@ -148,7 +149,7 @@ Build packages specifying multiple definition trees:
opts := util.SetSolverConfig() opts := util.SetSolverConfig()
pullRepo, _ := cmd.Flags().GetStringArray("pull-repository") pullRepo, _ := cmd.Flags().GetStringArray("pull-repository")
LuetCfg.GetGeneral().ShowBuildOutput = LuetCfg.Viper.GetBool("general.show_build_output") LuetCfg.GetGeneral().ShowBuildOutput = viper.GetBool("general.show_build_output")
Debug("Solver", opts.CompactString()) Debug("Solver", opts.CompactString())

View File

@ -18,8 +18,7 @@ package cmd_helpers_test
import ( import (
"testing" "testing"
. "github.com/mudler/luet/cmd" . "github.com/mudler/luet/cmd/util"
config "github.com/mudler/luet/pkg/config"
. "github.com/onsi/ginkgo" . "github.com/onsi/ginkgo"
. "github.com/onsi/gomega" . "github.com/onsi/gomega"
@ -27,6 +26,6 @@ import (
func TestSolver(t *testing.T) { func TestSolver(t *testing.T) {
RegisterFailHandler(Fail) RegisterFailHandler(Fail)
LoadConfig(config.LuetCfg) LoadConfig()
RunSpecs(t, "CLI helpers test Suite") RunSpecs(t, "CLI helpers test Suite")
} }

View File

@ -25,6 +25,7 @@ import (
pkg "github.com/mudler/luet/pkg/package" pkg "github.com/mudler/luet/pkg/package"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/viper"
) )
var installCmd = &cobra.Command{ var installCmd = &cobra.Command{
@ -50,10 +51,10 @@ To force install a package:
PreRun: func(cmd *cobra.Command, args []string) { PreRun: func(cmd *cobra.Command, args []string) {
util.BindSystemFlags(cmd) util.BindSystemFlags(cmd)
util.BindSolverFlags(cmd) util.BindSolverFlags(cmd)
LuetCfg.Viper.BindPFlag("onlydeps", cmd.Flags().Lookup("onlydeps")) viper.BindPFlag("onlydeps", cmd.Flags().Lookup("onlydeps"))
LuetCfg.Viper.BindPFlag("nodeps", cmd.Flags().Lookup("nodeps")) viper.BindPFlag("nodeps", cmd.Flags().Lookup("nodeps"))
LuetCfg.Viper.BindPFlag("force", cmd.Flags().Lookup("force")) viper.BindPFlag("force", cmd.Flags().Lookup("force"))
LuetCfg.Viper.BindPFlag("yes", cmd.Flags().Lookup("yes")) viper.BindPFlag("yes", cmd.Flags().Lookup("yes"))
}, },
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
var toInstall pkg.Packages var toInstall pkg.Packages
@ -66,10 +67,10 @@ To force install a package:
toInstall = append(toInstall, pack) toInstall = append(toInstall, pack)
} }
force := LuetCfg.Viper.GetBool("force") force := viper.GetBool("force")
nodeps := LuetCfg.Viper.GetBool("nodeps") nodeps := viper.GetBool("nodeps")
onlydeps := LuetCfg.Viper.GetBool("onlydeps") onlydeps := viper.GetBool("onlydeps")
yes := LuetCfg.Viper.GetBool("yes") yes := viper.GetBool("yes")
downloadOnly, _ := cmd.Flags().GetBool("download-only") downloadOnly, _ := cmd.Flags().GetBool("download-only")
finalizerEnvs, _ := cmd.Flags().GetStringArray("finalizer-env") finalizerEnvs, _ := cmd.Flags().GetStringArray("finalizer-env")
relax, _ := cmd.Flags().GetBool("relax") relax, _ := cmd.Flags().GetBool("relax")

View File

@ -22,6 +22,7 @@ import (
. "github.com/mudler/luet/pkg/logger" . "github.com/mudler/luet/pkg/logger"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/viper"
) )
var reclaimCmd = &cobra.Command{ var reclaimCmd = &cobra.Command{
@ -29,7 +30,7 @@ var reclaimCmd = &cobra.Command{
Short: "Reclaim packages to Luet database from available repositories", Short: "Reclaim packages to Luet database from available repositories",
PreRun: func(cmd *cobra.Command, args []string) { PreRun: func(cmd *cobra.Command, args []string) {
util.BindSystemFlags(cmd) util.BindSystemFlags(cmd)
LuetCfg.Viper.BindPFlag("force", cmd.Flags().Lookup("force")) viper.BindPFlag("force", cmd.Flags().Lookup("force"))
}, },
Long: `Reclaim tries to find association between packages in the online repositories and the system one. Long: `Reclaim tries to find association between packages in the online repositories and the system one.
@ -40,7 +41,7 @@ It scans the target file system, and if finds a match with a package available i
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
util.SetSystemConfig() util.SetSystemConfig()
force := LuetCfg.Viper.GetBool("force") force := viper.GetBool("force")
Debug("Solver", LuetCfg.GetSolverOptions().CompactString()) Debug("Solver", LuetCfg.GetSolverOptions().CompactString())

View File

@ -25,6 +25,7 @@ import (
pkg "github.com/mudler/luet/pkg/package" pkg "github.com/mudler/luet/pkg/package"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/viper"
) )
var reinstallCmd = &cobra.Command{ var reinstallCmd = &cobra.Command{
@ -37,19 +38,19 @@ var reinstallCmd = &cobra.Command{
PreRun: func(cmd *cobra.Command, args []string) { PreRun: func(cmd *cobra.Command, args []string) {
util.BindSystemFlags(cmd) util.BindSystemFlags(cmd)
util.BindSolverFlags(cmd) util.BindSolverFlags(cmd)
LuetCfg.Viper.BindPFlag("onlydeps", cmd.Flags().Lookup("onlydeps")) viper.BindPFlag("onlydeps", cmd.Flags().Lookup("onlydeps"))
LuetCfg.Viper.BindPFlag("force", cmd.Flags().Lookup("force")) viper.BindPFlag("force", cmd.Flags().Lookup("force"))
LuetCfg.Viper.BindPFlag("for", cmd.Flags().Lookup("for")) viper.BindPFlag("for", cmd.Flags().Lookup("for"))
LuetCfg.Viper.BindPFlag("yes", cmd.Flags().Lookup("yes")) viper.BindPFlag("yes", cmd.Flags().Lookup("yes"))
}, },
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
var toUninstall pkg.Packages var toUninstall pkg.Packages
var toAdd pkg.Packages var toAdd pkg.Packages
force := LuetCfg.Viper.GetBool("force") force := viper.GetBool("force")
onlydeps := LuetCfg.Viper.GetBool("onlydeps") onlydeps := viper.GetBool("onlydeps")
yes := LuetCfg.Viper.GetBool("yes") yes := viper.GetBool("yes")
downloadOnly, _ := cmd.Flags().GetBool("download-only") downloadOnly, _ := cmd.Flags().GetBool("download-only")

View File

@ -25,6 +25,7 @@ import (
pkg "github.com/mudler/luet/pkg/package" pkg "github.com/mudler/luet/pkg/package"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/viper"
) )
var replaceCmd = &cobra.Command{ var replaceCmd = &cobra.Command{
@ -38,22 +39,22 @@ var replaceCmd = &cobra.Command{
PreRun: func(cmd *cobra.Command, args []string) { PreRun: func(cmd *cobra.Command, args []string) {
util.BindSystemFlags(cmd) util.BindSystemFlags(cmd)
util.BindSolverFlags(cmd) util.BindSolverFlags(cmd)
LuetCfg.Viper.BindPFlag("onlydeps", cmd.Flags().Lookup("onlydeps")) viper.BindPFlag("onlydeps", cmd.Flags().Lookup("onlydeps"))
LuetCfg.Viper.BindPFlag("nodeps", cmd.Flags().Lookup("nodeps")) viper.BindPFlag("nodeps", cmd.Flags().Lookup("nodeps"))
LuetCfg.Viper.BindPFlag("force", cmd.Flags().Lookup("force")) viper.BindPFlag("force", cmd.Flags().Lookup("force"))
LuetCfg.Viper.BindPFlag("for", cmd.Flags().Lookup("for")) viper.BindPFlag("for", cmd.Flags().Lookup("for"))
LuetCfg.Viper.BindPFlag("yes", cmd.Flags().Lookup("yes")) viper.BindPFlag("yes", cmd.Flags().Lookup("yes"))
}, },
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
var toUninstall pkg.Packages var toUninstall pkg.Packages
var toAdd pkg.Packages var toAdd pkg.Packages
f := LuetCfg.Viper.GetStringSlice("for") f := viper.GetStringSlice("for")
force := LuetCfg.Viper.GetBool("force") force := viper.GetBool("force")
nodeps := LuetCfg.Viper.GetBool("nodeps") nodeps := viper.GetBool("nodeps")
onlydeps := LuetCfg.Viper.GetBool("onlydeps") onlydeps := viper.GetBool("onlydeps")
yes := LuetCfg.Viper.GetBool("yes") yes := viper.GetBool("yes")
downloadOnly, _ := cmd.Flags().GetBool("download-only") downloadOnly, _ := cmd.Flags().GetBool("download-only")
util.SetSystemConfig() util.SetSystemConfig()

View File

@ -53,24 +53,20 @@ $> luet repo update repo1 repo2
} }
r := installer.NewSystemRepository(*repo) r := installer.NewSystemRepository(*repo)
Spinner(32)
_, err = r.Sync(force) _, err = r.Sync(force)
if err != nil && !ignore { if err != nil && !ignore {
Fatal("Error on sync repository " + rname + ": " + err.Error()) Fatal("Error on sync repository " + rname + ": " + err.Error())
} }
SpinnerStop()
} }
} else { } else {
for _, repo := range LuetCfg.SystemRepositories { for _, repo := range LuetCfg.SystemRepositories {
if repo.Cached && repo.Enable { if repo.Cached && repo.Enable {
r := installer.NewSystemRepository(repo) r := installer.NewSystemRepository(repo)
Spinner(32)
_, err := r.Sync(force) _, err := r.Sync(force)
if err != nil && !ignore { if err != nil && !ignore {
Fatal("Error on sync repository " + r.GetName() + ": " + err.Error()) Fatal("Error on sync repository " + r.GetName() + ": " + err.Error())
} }
SpinnerStop()
} }
} }
} }

View File

@ -18,20 +18,13 @@ package cmd
import ( import (
"fmt" "fmt"
"os" "os"
"os/user"
"path/filepath"
"runtime"
"strings"
"github.com/marcsauter/single" "github.com/marcsauter/single"
"github.com/mudler/luet/cmd/util"
bus "github.com/mudler/luet/pkg/bus" bus "github.com/mudler/luet/pkg/bus"
fileHelper "github.com/mudler/luet/pkg/helpers/file"
extensions "github.com/mudler/cobra-extensions"
config "github.com/mudler/luet/pkg/config" config "github.com/mudler/luet/pkg/config"
helpers "github.com/mudler/luet/pkg/helpers"
. "github.com/mudler/luet/pkg/logger" . "github.com/mudler/luet/pkg/logger"
repo "github.com/mudler/luet/pkg/repository"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/viper" "github.com/spf13/viper"
) )
@ -63,18 +56,19 @@ func version() string {
return fmt.Sprintf("%s-g%s %s", LuetCLIVersion, BuildCommit, BuildTime) return fmt.Sprintf("%s-g%s %s", LuetCLIVersion, BuildCommit, BuildTime)
} }
var noBannerCommands = []string{"search", "exec", "tree", "database", "box", "cleanup"} var bannerCommands = []string{"install", "build", "uninstall", "upgrade"}
func displayVersionBanner() { func displayVersionBanner() {
display := true display := false
if len(os.Args) > 1 { if len(os.Args) > 1 {
for _, c := range noBannerCommands { for _, c := range bannerCommands {
if os.Args[1] == c { if os.Args[1] == c {
display = false display = true
} }
} }
} }
if display { if display {
util.IntroScreen()
Info("Luet version", version()) Info("Luet version", version())
Info(license) Info(license)
} }
@ -130,10 +124,11 @@ To build a package, from a tree definition:
Version: version(), Version: version(),
PersistentPreRun: func(cmd *cobra.Command, args []string) { PersistentPreRun: func(cmd *cobra.Command, args []string) {
err := LoadConfig(config.LuetCfg) _, err := util.LoadConfig()
if err != nil { if err != nil {
Fatal("failed to load configuration:", err.Error()) Fatal("failed to load configuration:", err.Error())
} }
// Initialize tmpdir prefix. TODO: Move this with LoadConfig // Initialize tmpdir prefix. TODO: Move this with LoadConfig
// directly on sub command to ensure the creation only when it's // directly on sub command to ensure the creation only when it's
// needed. // needed.
@ -164,41 +159,6 @@ To build a package, from a tree definition:
SilenceErrors: true, SilenceErrors: true,
} }
func LoadConfig(c *config.LuetConfig) error {
// If a config file is found, read it in.
c.Viper.ReadInConfig()
err := c.Viper.Unmarshal(&config.LuetCfg)
if err != nil {
return err
}
noSpinner := c.Viper.GetBool("no_spinner")
InitAurora()
if !noSpinner {
NewSpinner()
}
Debug("Using config file:", c.Viper.ConfigFileUsed())
if c.GetLogging().EnableLogFile && c.GetLogging().Path != "" {
// Init zap logger
err = ZapLogger()
if err != nil {
return err
}
}
// Load repositories
err = repo.LoadRepositories(c)
if err != nil {
return err
}
return nil
}
// Execute adds all child commands to the root command sets flags appropriately. // Execute adds all child commands to the root command sets flags appropriately.
// This is called by main.main(). It only needs to happen once to the rootCmd. // This is called by main.main(). It only needs to happen once to the rootCmd.
func Execute() { func Execute() {
@ -213,95 +173,5 @@ func Execute() {
} }
func init() { func init() {
cobra.OnInitialize(initConfig) util.InitViper(RootCmd)
pflags := RootCmd.PersistentFlags()
pflags.StringVar(&cfgFile, "config", "", "config file (default is $HOME/.luet.yaml)")
pflags.BoolP("debug", "d", false, "verbose output")
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", config.LuetCfg.GetLogging().Color, "Enable/Disable color.")
pflags.Bool("emoji", config.LuetCfg.GetLogging().EnableEmoji, "Enable/Disable emoji.")
pflags.Bool("skip-config-protect", config.LuetCfg.ConfigProtectSkip,
"Disable config protect analysis.")
pflags.StringP("logfile", "l", config.LuetCfg.GetLogging().Path,
"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 {
Warning("failed to retrieve user identity:", err.Error())
}
pflags.Bool("same-owner", config.LuetCfg.GetGeneral().SameOwner, "Maintain same owner on uncompress.")
pflags.Int("concurrency", runtime.NumCPU(), "Concurrency")
config.LuetCfg.Viper.BindPFlag("logging.color", pflags.Lookup("color"))
config.LuetCfg.Viper.BindPFlag("logging.enable_emoji", pflags.Lookup("emoji"))
config.LuetCfg.Viper.BindPFlag("logging.enable_logfile", pflags.Lookup("enable-logfile"))
config.LuetCfg.Viper.BindPFlag("logging.path", pflags.Lookup("logfile"))
config.LuetCfg.Viper.BindPFlag("general.concurrency", pflags.Lookup("concurrency"))
config.LuetCfg.Viper.BindPFlag("general.debug", pflags.Lookup("debug"))
config.LuetCfg.Viper.BindPFlag("general.fatal_warnings", pflags.Lookup("fatal"))
config.LuetCfg.Viper.BindPFlag("general.same_owner", pflags.Lookup("same-owner"))
config.LuetCfg.Viper.BindPFlag("plugin", pflags.Lookup("plugin"))
// Currently I maintain this only from cli.
config.LuetCfg.Viper.BindPFlag("no_spinner", pflags.Lookup("no-spinner"))
config.LuetCfg.Viper.BindPFlag("config_protect_skip", pflags.Lookup("skip-config-protect"))
// Extensions must be binary with the "luet-" prefix to be able to be shown in the help.
// we also accept extensions in the relative path where luet is being started, "extensions/"
exts := extensions.Discover("luet", "extensions")
for _, ex := range exts {
cobraCmd := ex.CobraCommand()
RootCmd.AddCommand(cobraCmd)
}
}
// initConfig reads in config file and ENV variables if set.
func initConfig() {
// Luet support these priorities on read configuration file:
// - command line option (if available)
// - $PWD/.luet.yaml
// - $HOME/.luet.yaml
// - /etc/luet/luet.yaml
//
// Note: currently a single viper instance support only one config name.
viper.SetEnvPrefix(LuetEnvPrefix)
viper.SetConfigType("yaml")
if cfgFile != "" { // enable ability to specify config file via flag
viper.SetConfigFile(cfgFile)
} else {
// Retrieve pwd directory
pwdDir, err := os.Getwd()
if err != nil {
Error(err)
os.Exit(1)
}
homeDir := helpers.GetHomeDir()
if fileHelper.Exists(filepath.Join(pwdDir, ".luet.yaml")) || (homeDir != "" && fileHelper.Exists(filepath.Join(homeDir, ".luet.yaml"))) {
viper.AddConfigPath(".")
if homeDir != "" {
viper.AddConfigPath(homeDir)
}
viper.SetConfigName(".luet")
} else {
viper.SetConfigName("luet")
viper.AddConfigPath("/etc/luet")
}
}
viper.AutomaticEnv() // read in environment variables that match
// Create EnvKey Replacer for handle complex structure
replacer := strings.NewReplacer(".", "__")
viper.SetEnvKeyReplacer(replacer)
viper.SetTypeByDefaultValue(true)
} }

View File

@ -27,6 +27,7 @@ import (
. "github.com/mudler/luet/pkg/logger" . "github.com/mudler/luet/pkg/logger"
pkg "github.com/mudler/luet/pkg/package" pkg "github.com/mudler/luet/pkg/package"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/viper"
) )
type PackageResult struct { type PackageResult struct {
@ -291,7 +292,7 @@ Search can also return results in the terminal in different ways: as terminal ou
PreRun: func(cmd *cobra.Command, args []string) { PreRun: func(cmd *cobra.Command, args []string) {
util.BindSystemFlags(cmd) util.BindSystemFlags(cmd)
util.BindSolverFlags(cmd) util.BindSolverFlags(cmd)
LuetCfg.Viper.BindPFlag("installed", cmd.Flags().Lookup("installed")) viper.BindPFlag("installed", cmd.Flags().Lookup("installed"))
}, },
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
var results Results var results Results
@ -302,7 +303,7 @@ Search can also return results in the terminal in different ways: as terminal ou
} }
hidden, _ := cmd.Flags().GetBool("hidden") hidden, _ := cmd.Flags().GetBool("hidden")
installed := LuetCfg.Viper.GetBool("installed") installed := viper.GetBool("installed")
searchWithLabel, _ := cmd.Flags().GetBool("by-label") searchWithLabel, _ := cmd.Flags().GetBool("by-label")
searchWithLabelMatch, _ := cmd.Flags().GetBool("by-label-regex") searchWithLabelMatch, _ := cmd.Flags().GetBool("by-label-regex")
revdeps, _ := cmd.Flags().GetBool("revdeps") revdeps, _ := cmd.Flags().GetBool("revdeps")

View File

@ -241,7 +241,7 @@ func validatePackage(p pkg.Package, checkType string, opts *ValidateOpts, recipe
continue continue
} }
Spinner(32) Spinner(22)
solution, err := depSolver.Install(pkg.Packages{r}) solution, err := depSolver.Install(pkg.Packages{r})
ass := solution.SearchByName(r.GetPackageName()) ass := solution.SearchByName(r.GetPackageName())
SpinnerStop() SpinnerStop()

View File

@ -24,6 +24,7 @@ import (
"github.com/mudler/luet/pkg/solver" "github.com/mudler/luet/pkg/solver"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/viper"
) )
var uninstallCmd = &cobra.Command{ var uninstallCmd = &cobra.Command{
@ -34,9 +35,9 @@ var uninstallCmd = &cobra.Command{
PreRun: func(cmd *cobra.Command, args []string) { PreRun: func(cmd *cobra.Command, args []string) {
util.BindSystemFlags(cmd) util.BindSystemFlags(cmd)
util.BindSolverFlags(cmd) util.BindSolverFlags(cmd)
LuetCfg.Viper.BindPFlag("nodeps", cmd.Flags().Lookup("nodeps")) viper.BindPFlag("nodeps", cmd.Flags().Lookup("nodeps"))
LuetCfg.Viper.BindPFlag("force", cmd.Flags().Lookup("force")) viper.BindPFlag("force", cmd.Flags().Lookup("force"))
LuetCfg.Viper.BindPFlag("yes", cmd.Flags().Lookup("yes")) viper.BindPFlag("yes", cmd.Flags().Lookup("yes"))
}, },
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
toRemove := []pkg.Package{} toRemove := []pkg.Package{}
@ -49,12 +50,12 @@ var uninstallCmd = &cobra.Command{
toRemove = append(toRemove, pack) toRemove = append(toRemove, pack)
} }
force := LuetCfg.Viper.GetBool("force") force := viper.GetBool("force")
nodeps, _ := cmd.Flags().GetBool("nodeps") nodeps, _ := cmd.Flags().GetBool("nodeps")
full, _ := cmd.Flags().GetBool("full") full, _ := cmd.Flags().GetBool("full")
checkconflicts, _ := cmd.Flags().GetBool("conflictscheck") checkconflicts, _ := cmd.Flags().GetBool("conflictscheck")
fullClean, _ := cmd.Flags().GetBool("full-clean") fullClean, _ := cmd.Flags().GetBool("full-clean")
yes := LuetCfg.Viper.GetBool("yes") yes := viper.GetBool("yes")
keepProtected, _ := cmd.Flags().GetBool("keep-protected-files") keepProtected, _ := cmd.Flags().GetBool("keep-protected-files")
util.SetSystemConfig() util.SetSystemConfig()

View File

@ -22,6 +22,7 @@ import (
"github.com/mudler/luet/pkg/solver" "github.com/mudler/luet/pkg/solver"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/viper"
) )
var upgradeCmd = &cobra.Command{ var upgradeCmd = &cobra.Command{
@ -31,19 +32,19 @@ var upgradeCmd = &cobra.Command{
PreRun: func(cmd *cobra.Command, args []string) { PreRun: func(cmd *cobra.Command, args []string) {
util.BindSystemFlags(cmd) util.BindSystemFlags(cmd)
util.BindSolverFlags(cmd) util.BindSolverFlags(cmd)
LuetCfg.Viper.BindPFlag("force", cmd.Flags().Lookup("force")) viper.BindPFlag("force", cmd.Flags().Lookup("force"))
LuetCfg.Viper.BindPFlag("yes", cmd.Flags().Lookup("yes")) viper.BindPFlag("yes", cmd.Flags().Lookup("yes"))
}, },
Long: `Upgrades packages in parallel`, Long: `Upgrades packages in parallel`,
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
force := LuetCfg.Viper.GetBool("force") force := viper.GetBool("force")
nodeps, _ := cmd.Flags().GetBool("nodeps") nodeps, _ := cmd.Flags().GetBool("nodeps")
full, _ := cmd.Flags().GetBool("full") full, _ := cmd.Flags().GetBool("full")
universe, _ := cmd.Flags().GetBool("universe") universe, _ := cmd.Flags().GetBool("universe")
clean, _ := cmd.Flags().GetBool("clean") clean, _ := cmd.Flags().GetBool("clean")
sync, _ := cmd.Flags().GetBool("sync") sync, _ := cmd.Flags().GetBool("sync")
yes := LuetCfg.Viper.GetBool("yes") yes := viper.GetBool("yes")
downloadOnly, _ := cmd.Flags().GetBool("download-only") downloadOnly, _ := cmd.Flags().GetBool("download-only")
util.SetSystemConfig() util.SetSystemConfig()

View File

@ -20,7 +20,9 @@ import (
"path/filepath" "path/filepath"
"strings" "strings"
"github.com/pterm/pterm"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/viper"
"github.com/mudler/luet/pkg/config" "github.com/mudler/luet/pkg/config"
. "github.com/mudler/luet/pkg/config" . "github.com/mudler/luet/pkg/config"
@ -28,30 +30,30 @@ import (
) )
func BindSystemFlags(cmd *cobra.Command) { func BindSystemFlags(cmd *cobra.Command) {
LuetCfg.Viper.BindPFlag("system.database_path", cmd.Flags().Lookup("system-dbpath")) viper.BindPFlag("system.database_path", cmd.Flags().Lookup("system-dbpath"))
LuetCfg.Viper.BindPFlag("system.rootfs", cmd.Flags().Lookup("system-target")) viper.BindPFlag("system.rootfs", cmd.Flags().Lookup("system-target"))
LuetCfg.Viper.BindPFlag("system.database_engine", cmd.Flags().Lookup("system-engine")) viper.BindPFlag("system.database_engine", cmd.Flags().Lookup("system-engine"))
} }
func BindSolverFlags(cmd *cobra.Command) { func BindSolverFlags(cmd *cobra.Command) {
LuetCfg.Viper.BindPFlag("solver.type", cmd.Flags().Lookup("solver-type")) viper.BindPFlag("solver.type", cmd.Flags().Lookup("solver-type"))
LuetCfg.Viper.BindPFlag("solver.discount", cmd.Flags().Lookup("solver-discount")) viper.BindPFlag("solver.discount", cmd.Flags().Lookup("solver-discount"))
LuetCfg.Viper.BindPFlag("solver.rate", cmd.Flags().Lookup("solver-rate")) viper.BindPFlag("solver.rate", cmd.Flags().Lookup("solver-rate"))
LuetCfg.Viper.BindPFlag("solver.max_attempts", cmd.Flags().Lookup("solver-attempts")) viper.BindPFlag("solver.max_attempts", cmd.Flags().Lookup("solver-attempts"))
} }
func BindValuesFlags(cmd *cobra.Command) { func BindValuesFlags(cmd *cobra.Command) {
LuetCfg.Viper.BindPFlag("values", cmd.Flags().Lookup("values")) viper.BindPFlag("values", cmd.Flags().Lookup("values"))
} }
func ValuesFlags() []string { func ValuesFlags() []string {
return LuetCfg.Viper.GetStringSlice("values") return viper.GetStringSlice("values")
} }
func SetSystemConfig() { func SetSystemConfig() {
dbpath := LuetCfg.Viper.GetString("system.database_path") dbpath := viper.GetString("system.database_path")
rootfs := LuetCfg.Viper.GetString("system.rootfs") rootfs := viper.GetString("system.rootfs")
engine := LuetCfg.Viper.GetString("system.database_engine") engine := viper.GetString("system.database_engine")
LuetCfg.System.DatabaseEngine = engine LuetCfg.System.DatabaseEngine = engine
LuetCfg.System.DatabasePath = dbpath LuetCfg.System.DatabasePath = dbpath
@ -59,10 +61,10 @@ func SetSystemConfig() {
} }
func SetSolverConfig() (c *config.LuetSolverOptions) { func SetSolverConfig() (c *config.LuetSolverOptions) {
stype := LuetCfg.Viper.GetString("solver.type") stype := viper.GetString("solver.type")
discount := LuetCfg.Viper.GetFloat64("solver.discount") discount := viper.GetFloat64("solver.discount")
rate := LuetCfg.Viper.GetFloat64("solver.rate") rate := viper.GetFloat64("solver.rate")
attempts := LuetCfg.Viper.GetInt("solver.max_attempts") attempts := viper.GetInt("solver.max_attempts")
LuetCfg.GetSolverOptions().Type = stype LuetCfg.GetSolverOptions().Type = stype
LuetCfg.GetSolverOptions().LearnRate = float32(rate) LuetCfg.GetSolverOptions().LearnRate = float32(rate)
@ -106,3 +108,14 @@ func TemplateFolders(fromRepo bool, treePaths []string) []string {
} }
return templateFolders return templateFolders
} }
func IntroScreen() {
luetLogo, _ := pterm.DefaultBigText.WithLetters(
pterm.NewLettersFromStringWithStyle("LU", pterm.NewStyle(pterm.FgLightMagenta)),
pterm.NewLettersFromStringWithStyle("ET", pterm.NewStyle(pterm.FgLightBlue))).
Srender()
pterm.DefaultCenter.Print(luetLogo)
pterm.DefaultCenter.Print(pterm.DefaultHeader.WithFullWidth().WithBackgroundStyle(pterm.NewStyle(pterm.BgLightBlue)).WithMargin(10).Sprint("Luet - 0-deps container-based package manager"))
}

217
cmd/util/config.go Normal file
View File

@ -0,0 +1,217 @@
package util
import (
"fmt"
"os"
"os/user"
"path/filepath"
"runtime"
"strings"
extensions "github.com/mudler/cobra-extensions"
. "github.com/mudler/luet/pkg/logger"
"github.com/mudler/luet/pkg/config"
helpers "github.com/mudler/luet/pkg/helpers"
fileHelper "github.com/mudler/luet/pkg/helpers/file"
"github.com/mudler/luet/pkg/helpers/terminal"
repo "github.com/mudler/luet/pkg/repository"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
const (
LuetEnvPrefix = "LUET"
)
var cfgFile string
// initConfig reads in config file and ENV variables if set.
func initConfig() {
// Luet support these priorities on read configuration file:
// - command line option (if available)
// - $PWD/.luet.yaml
// - $HOME/.luet.yaml
// - /etc/luet/luet.yaml
//
// Note: currently a single viper instance support only one config name.
viper.SetEnvPrefix(LuetEnvPrefix)
viper.SetConfigType("yaml")
if cfgFile != "" { // enable ability to specify config file via flag
viper.SetConfigFile(cfgFile)
} else {
// Retrieve pwd directory
pwdDir, err := os.Getwd()
if err != nil {
Error(err)
os.Exit(1)
}
homeDir := helpers.GetHomeDir()
if fileHelper.Exists(filepath.Join(pwdDir, ".luet.yaml")) || (homeDir != "" && fileHelper.Exists(filepath.Join(homeDir, ".luet.yaml"))) {
viper.AddConfigPath(".")
if homeDir != "" {
viper.AddConfigPath(homeDir)
}
viper.SetConfigName(".luet")
} else {
viper.SetConfigName("luet")
viper.AddConfigPath("/etc/luet")
}
}
viper.AutomaticEnv() // read in environment variables that match
// Create EnvKey Replacer for handle complex structure
replacer := strings.NewReplacer(".", "__")
viper.SetEnvKeyReplacer(replacer)
viper.SetTypeByDefaultValue(true)
}
func LoadConfig() (cc config.LuetConfig, err error) {
setDefaults(viper.GetViper())
initConfig()
// If a config file is found, read it in.
err = viper.ReadInConfig()
if err != nil {
return
}
err = viper.Unmarshal(&cc)
if err != nil {
return
}
if terminal.IsTerminal(os.Stdout) {
noSpinner := viper.GetBool("no_spinner")
InitAurora()
if !noSpinner {
NewSpinner()
}
noColor := viper.GetBool("logging.color")
if noColor {
fmt.Println("Disabling color")
NoColor()
}
} else {
fmt.Println("Not a terminal, disabling color")
NoColor()
}
Debug("Using config file:", viper.ConfigFileUsed())
if cc.GetLogging().EnableLogFile && cc.GetLogging().Path != "" {
// Init zap logger
err = ZapLogger()
if err != nil {
return
}
}
// Load repositories
err = repo.LoadRepositories(&cc)
if err != nil {
return
}
config.LuetCfg = &cc
return
}
func setDefaults(viper *viper.Viper) {
viper.SetDefault("logging.level", "info")
viper.SetDefault("logging.enable_logfile", false)
viper.SetDefault("logging.path", "/var/log/luet.log")
viper.SetDefault("logging.json_format", false)
viper.SetDefault("logging.enable_emoji", true)
viper.SetDefault("logging.color", true)
viper.SetDefault("general.concurrency", runtime.NumCPU())
viper.SetDefault("general.debug", false)
viper.SetDefault("general.show_build_output", false)
viper.SetDefault("general.spinner_ms", 100)
viper.SetDefault("general.spinner_charset", 22)
viper.SetDefault("general.fatal_warnings", false)
u, err := user.Current()
// os/user doesn't work in from scratch environments
if err != nil || (u != nil && u.Uid == "0") {
viper.SetDefault("general.same_owner", true)
} else {
viper.SetDefault("general.same_owner", false)
}
viper.SetDefault("system.database_engine", "boltdb")
viper.SetDefault("system.database_path", "/var/cache/luet")
viper.SetDefault("system.rootfs", "/")
viper.SetDefault("system.tmpdir_base", filepath.Join(os.TempDir(), "tmpluet"))
viper.SetDefault("system.pkgs_cache_path", "packages")
viper.SetDefault("repos_confdir", []string{"/etc/luet/repos.conf.d"})
viper.SetDefault("config_protect_confdir", []string{"/etc/luet/config.protect.d"})
viper.SetDefault("config_protect_skip", false)
// TODO: Set default to false when we are ready for migration.
viper.SetDefault("config_from_host", true)
viper.SetDefault("cache_repositories", []string{})
viper.SetDefault("system_repositories", []string{})
viper.SetDefault("finalizer_envs", make(map[string]string, 0))
viper.SetDefault("solver.type", "")
viper.SetDefault("solver.rate", 0.7)
viper.SetDefault("solver.discount", 1.0)
viper.SetDefault("solver.max_attempts", 9000)
}
func InitViper(RootCmd *cobra.Command) {
cobra.OnInitialize(initConfig)
pflags := RootCmd.PersistentFlags()
pflags.StringVar(&cfgFile, "config", "", "config file (default is $HOME/.luet.yaml)")
pflags.BoolP("debug", "d", false, "verbose output")
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", config.LuetCfg.GetLogging().Color, "Enable/Disable color.")
pflags.Bool("emoji", config.LuetCfg.GetLogging().EnableEmoji, "Enable/Disable emoji.")
pflags.Bool("skip-config-protect", config.LuetCfg.ConfigProtectSkip,
"Disable config protect analysis.")
pflags.StringP("logfile", "l", config.LuetCfg.GetLogging().Path,
"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 {
Warning("failed to retrieve user identity:", err.Error())
}
pflags.Bool("same-owner", config.LuetCfg.GetGeneral().SameOwner, "Maintain same owner on uncompress.")
pflags.Int("concurrency", runtime.NumCPU(), "Concurrency")
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("general.concurrency", pflags.Lookup("concurrency"))
viper.BindPFlag("general.debug", pflags.Lookup("debug"))
viper.BindPFlag("general.fatal_warnings", pflags.Lookup("fatal"))
viper.BindPFlag("general.same_owner", pflags.Lookup("same-owner"))
viper.BindPFlag("plugin", pflags.Lookup("plugin"))
// Currently I maintain this only from cli.
viper.BindPFlag("no_spinner", pflags.Lookup("no-spinner"))
viper.BindPFlag("config_protect_skip", pflags.Lookup("skip-config-protect"))
// Extensions must be binary with the "luet-" prefix to be able to be shown in the help.
// we also accept extensions in the relative path where luet is being started, "extensions/"
exts := extensions.Discover("luet", "extensions")
for _, ex := range exts {
cobraCmd := ex.CobraCommand()
RootCmd.AddCommand(cobraCmd)
}
}

8
go.mod
View File

@ -11,7 +11,6 @@ require (
github.com/apex/log v1.9.0 // indirect github.com/apex/log v1.9.0 // indirect
github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef
github.com/asdine/storm v0.0.0-20190418133842-e0f77eada154 github.com/asdine/storm v0.0.0-20190418133842-e0f77eada154
github.com/briandowns/spinner v1.12.1-0.20201220203425-e201aaea0a31
github.com/cavaliercoder/grab v1.0.1-0.20201108051000-98a5bfe305ec github.com/cavaliercoder/grab v1.0.1-0.20201108051000-98a5bfe305ec
github.com/containerd/cgroups v0.0.0-20200217135630-d732e370d46d // indirect github.com/containerd/cgroups v0.0.0-20200217135630-d732e370d46d // indirect
github.com/containerd/containerd v1.4.1-0.20201117152358-0edc412565dc github.com/containerd/containerd v1.4.1-0.20201117152358-0edc412565dc
@ -22,7 +21,6 @@ require (
github.com/docker/docker v20.10.0-beta1.0.20201110211921-af34b94a78a1+incompatible github.com/docker/docker v20.10.0-beta1.0.20201110211921-af34b94a78a1+incompatible
github.com/docker/go-units v0.4.0 github.com/docker/go-units v0.4.0
github.com/ecooper/qlearning v0.0.0-20160612200101-3075011a69fd github.com/ecooper/qlearning v0.0.0-20160612200101-3075011a69fd
github.com/fatih/color v1.12.0 // indirect
github.com/fsnotify/fsnotify v1.5.1 // indirect github.com/fsnotify/fsnotify v1.5.1 // indirect
github.com/ghodss/yaml v1.0.0 github.com/ghodss/yaml v1.0.0
github.com/go-sql-driver/mysql v1.6.0 // indirect github.com/go-sql-driver/mysql v1.6.0 // indirect
@ -31,6 +29,7 @@ require (
github.com/google/go-containerregistry v0.2.1 github.com/google/go-containerregistry v0.2.1
github.com/google/renameio v1.0.0 github.com/google/renameio v1.0.0
github.com/google/uuid v1.3.0 // indirect github.com/google/uuid v1.3.0 // indirect
github.com/gookit/color v1.5.0 // indirect
github.com/hashicorp/go-multierror v1.0.0 github.com/hashicorp/go-multierror v1.0.0
github.com/hashicorp/go-version v1.3.0 github.com/hashicorp/go-version v1.3.0
github.com/huandu/xstrings v1.3.2 // indirect github.com/huandu/xstrings v1.3.2 // indirect
@ -44,7 +43,6 @@ require (
github.com/kyokomi/emoji v2.1.0+incompatible github.com/kyokomi/emoji v2.1.0+incompatible
github.com/logrusorgru/aurora v0.0.0-20190417123914-21d75270181e github.com/logrusorgru/aurora v0.0.0-20190417123914-21d75270181e
github.com/marcsauter/single v0.0.0-20181104081128-f8bf46f26ec0 github.com/marcsauter/single v0.0.0-20181104081128-f8bf46f26ec0
github.com/mattn/go-isatty v0.0.13 // indirect
github.com/mitchellh/copystructure v1.2.0 // indirect github.com/mitchellh/copystructure v1.2.0 // indirect
github.com/mitchellh/hashstructure/v2 v2.0.1 github.com/mitchellh/hashstructure/v2 v2.0.1
github.com/mitchellh/mapstructure v1.4.2 // indirect github.com/mitchellh/mapstructure v1.4.2 // indirect
@ -62,8 +60,8 @@ require (
github.com/pelletier/go-toml v1.9.4 // indirect github.com/pelletier/go-toml v1.9.4 // indirect
github.com/philopon/go-toposort v0.0.0-20170620085441-9be86dbd762f github.com/philopon/go-toposort v0.0.0-20170620085441-9be86dbd762f
github.com/pkg/errors v0.9.1 github.com/pkg/errors v0.9.1
github.com/pterm/pterm v0.12.32-0.20211002183613-ada9ef6790c3
github.com/rancher-sandbox/gofilecache v0.0.0-20210330135715-becdeff5df15 github.com/rancher-sandbox/gofilecache v0.0.0-20210330135715-becdeff5df15
github.com/schollz/progressbar/v3 v3.7.1
github.com/sirupsen/logrus v1.8.1 github.com/sirupsen/logrus v1.8.1
github.com/spf13/cast v1.4.1 // indirect github.com/spf13/cast v1.4.1 // indirect
github.com/spf13/cobra v1.2.1 github.com/spf13/cobra v1.2.1
@ -75,6 +73,8 @@ require (
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 // indirect golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 // indirect
golang.org/x/mod v0.4.2 golang.org/x/mod v0.4.2
golang.org/x/oauth2 v0.0.0-20210810183815-faf39c7919d5 // indirect golang.org/x/oauth2 v0.0.0-20210810183815-faf39c7919d5 // indirect
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654 // indirect
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect
google.golang.org/genproto v0.0.0-20210811021853-ddbe55d93216 // indirect google.golang.org/genproto v0.0.0-20210811021853-ddbe55d93216 // indirect
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect

46
go.sum
View File

@ -78,6 +78,10 @@ github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go
github.com/Luet-lab/moby v17.12.0-ce-rc1.0.20200605210607-749178b8f80d+incompatible h1:YddBuPhhRLoz7uhSJ3Zm//e62jQeTW/qXEZrk5I4qsk= github.com/Luet-lab/moby v17.12.0-ce-rc1.0.20200605210607-749178b8f80d+incompatible h1:YddBuPhhRLoz7uhSJ3Zm//e62jQeTW/qXEZrk5I4qsk=
github.com/Luet-lab/moby v17.12.0-ce-rc1.0.20200605210607-749178b8f80d+incompatible/go.mod h1:/XyFFC7lL96pE2kKmar2jd4LKxWzy1MmbiDHV0nK3bU= github.com/Luet-lab/moby v17.12.0-ce-rc1.0.20200605210607-749178b8f80d+incompatible/go.mod h1:/XyFFC7lL96pE2kKmar2jd4LKxWzy1MmbiDHV0nK3bU=
github.com/MakeNowJust/heredoc v0.0.0-20170808103936-bb23615498cd/go.mod h1:64YHyfSL2R96J44Nlwm39UHepQbyR5q10x7iYa1ks2E= github.com/MakeNowJust/heredoc v0.0.0-20170808103936-bb23615498cd/go.mod h1:64YHyfSL2R96J44Nlwm39UHepQbyR5q10x7iYa1ks2E=
github.com/MarvinJWendt/testza v0.1.0/go.mod h1:7AxNvlfeHP7Z/hDQ5JtE3OKYT3XFUeLCDE2DQninSqs=
github.com/MarvinJWendt/testza v0.2.1/go.mod h1:God7bhG8n6uQxwdScay+gjm9/LnO4D3kkcZX4hv9Rp8=
github.com/MarvinJWendt/testza v0.2.9 h1:JTa1DprTjXFC36VmlBjHA/5NdZN8eP3cz68X60rsPAg=
github.com/MarvinJWendt/testza v0.2.9/go.mod h1:nwIcjmr0Zz+Rcwfh3/4UhBp7ePKVhuBExvZqnKYWlII=
github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI=
github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
@ -142,6 +146,8 @@ github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef h1:46PFijGL
github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
github.com/asdine/storm v0.0.0-20190418133842-e0f77eada154 h1:2lbe+CPe6eQf2EA3jjLdLFZKGv3cbYqVIDjKnzcyOXg= github.com/asdine/storm v0.0.0-20190418133842-e0f77eada154 h1:2lbe+CPe6eQf2EA3jjLdLFZKGv3cbYqVIDjKnzcyOXg=
github.com/asdine/storm v0.0.0-20190418133842-e0f77eada154/go.mod h1:cMLKpjHSP4q0P133fV15ojQgwWWB2IMv+hrFsmBF/wI= github.com/asdine/storm v0.0.0-20190418133842-e0f77eada154/go.mod h1:cMLKpjHSP4q0P133fV15ojQgwWWB2IMv+hrFsmBF/wI=
github.com/atomicgo/cursor v0.0.1 h1:xdogsqa6YYlLfM+GyClC/Lchf7aiMerFiZQn7soTOoU=
github.com/atomicgo/cursor v0.0.1/go.mod h1:cBON2QmmrysudxNBFthvMtN32r3jxVRIvzkUiF/RuIk=
github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU=
github.com/aws/aws-sdk-go v1.15.11/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0= github.com/aws/aws-sdk-go v1.15.11/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0=
github.com/aws/aws-sdk-go v1.20.6/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.20.6/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
@ -164,8 +170,6 @@ github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqO
github.com/blang/semver v3.1.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/blang/semver v3.1.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
github.com/blang/semver v3.5.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/blang/semver v3.5.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4=
github.com/briandowns/spinner v1.12.1-0.20201220203425-e201aaea0a31 h1:yInAg9pE5qGec5eQ7XdfOTTaGwGxD3bKFVjmD6VKkwc=
github.com/briandowns/spinner v1.12.1-0.20201220203425-e201aaea0a31/go.mod h1:QOuQk7x+EaDASo80FEXwlwiA+j/PPIcX3FScO+3/ZPQ=
github.com/bshuster-repo/logrus-logstash-hook v0.4.1/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk= github.com/bshuster-repo/logrus-logstash-hook v0.4.1/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk=
github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8= github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8=
github.com/bugsnag/bugsnag-go v1.0.5-0.20150529004307-13fd6b8acda0 h1:s7+5BfS4WFJoVF9pnB8kBk03S7pZXRdKamnV0FOl5Sc= github.com/bugsnag/bugsnag-go v1.0.5-0.20150529004307-13fd6b8acda0 h1:s7+5BfS4WFJoVF9pnB8kBk03S7pZXRdKamnV0FOl5Sc=
@ -305,8 +309,6 @@ github.com/evanphx/json-patch v0.0.0-20200808040245-162e5629780b/go.mod h1:NAJj0
github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d/go.mod h1:ZZMPRZwes7CROmyNKgQzC3XPs6L/G2EJLHddWejkmf4= github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d/go.mod h1:ZZMPRZwes7CROmyNKgQzC3XPs6L/G2EJLHddWejkmf4=
github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc= github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fatih/color v1.12.0 h1:mRhaKNwANqRgUBGKmnI5ZxEk7QXmjQeCcuYFMX2bfcc=
github.com/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM=
github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4=
github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20=
@ -501,6 +503,9 @@ github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsC
github.com/googleapis/gnostic v0.1.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= github.com/googleapis/gnostic v0.1.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
github.com/googleapis/gnostic v0.2.2 h1:DcFegQ7+ECdmkJMfVwWlC+89I4esJ7p8nkGt9ainGDk= github.com/googleapis/gnostic v0.2.2 h1:DcFegQ7+ECdmkJMfVwWlC+89I4esJ7p8nkGt9ainGDk=
github.com/googleapis/gnostic v0.2.2/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= github.com/googleapis/gnostic v0.2.2/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
github.com/gookit/color v1.4.2/go.mod h1:fqRyamkC1W8uxl+lxCQxOT09l/vYfZ+QeiX3rKQHCoQ=
github.com/gookit/color v1.5.0 h1:1Opow3+BWDwqor78DcJkJCIwnkviFi+rrOANki9BUFw=
github.com/gookit/color v1.5.0/go.mod h1:43aQb+Zerm/BWh2GnrgOQm7ffz7tvQXEKV6BFMl7wAo=
github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8= github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
@ -605,7 +610,6 @@ github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/X
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/juju/loggo v0.0.0-20190526231331-6e530bcce5d8/go.mod h1:vgyd7OREkbtVEN/8IXZe5Ooef3LQePvuBm9UWj6ZL8U= github.com/juju/loggo v0.0.0-20190526231331-6e530bcce5d8/go.mod h1:vgyd7OREkbtVEN/8IXZe5Ooef3LQePvuBm9UWj6ZL8U=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/k0kubun/go-ansi v0.0.0-20180517002512-3bf9e2903213/go.mod h1:vNUNkEQ1e29fT/6vq2aBdFsgNPmy8qMdSay1npru+Sw=
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
@ -665,21 +669,17 @@ 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-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ=
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8=
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= 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.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-isatty v0.0.13 h1:qdl+GuBjcsKKDco5BsxPJlId98mSWNKqYA+Co0SC1yA=
github.com/mattn/go-isatty v0.0.13/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-oci8 v0.0.7/go.mod h1:wjDx6Xm9q7dFtHJvIlrI99JytznLw5wQ4R+9mNXJwGI= 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.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU=
github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/mattn/go-shellwords v1.0.10/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y= github.com/mattn/go-shellwords v1.0.10/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y=
github.com/mattn/go-sqlite3 v1.6.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/mattn/go-sqlite3 v1.6.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
@ -693,8 +693,6 @@ github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3N
github.com/miekg/pkcs11 v1.0.2 h1:CIBkOawOtzJNE0B+EpRiUBzuVW7JEQAwdwhSS6YhIeg= github.com/miekg/pkcs11 v1.0.2 h1:CIBkOawOtzJNE0B+EpRiUBzuVW7JEQAwdwhSS6YhIeg=
github.com/miekg/pkcs11 v1.0.2/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= github.com/miekg/pkcs11 v1.0.2/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs=
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db h1:62I3jR2EmQ4l5rM/4FEfDWcRD+abF5XlKShorW5LRoQ=
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db/go.mod h1:l0dey0ia/Uv7NcFFVbCLtqEBQbrT4OCwCSKTEv6enCw=
github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw=
github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw=
github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=
@ -877,10 +875,17 @@ github.com/prometheus/procfs v0.0.5/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDa
github.com/prometheus/procfs v0.0.8 h1:+fpWZdT24pJBiqJdAwYBjPSk+5YmQzYNPYzQsdzLkt8= github.com/prometheus/procfs v0.0.8 h1:+fpWZdT24pJBiqJdAwYBjPSk+5YmQzYNPYzQsdzLkt8=
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
github.com/pterm/pterm v0.12.27/go.mod h1:PhQ89w4i95rhgE+xedAoqous6K9X+r6aSOI2eFF7DZI=
github.com/pterm/pterm v0.12.29/go.mod h1:WI3qxgvoQFFGKGjGnJR849gU0TsEOvKn5Q8LlY1U7lg=
github.com/pterm/pterm v0.12.30/go.mod h1:MOqLIyMOgmTDz9yorcYbcw+HsgoZo3BQfg2wtl3HEFE=
github.com/pterm/pterm v0.12.32-0.20211002183613-ada9ef6790c3 h1:cJVCvrFnw/qdofx7T1jZETeSqJAwe/QYBLODPDwkelQ=
github.com/pterm/pterm v0.12.32-0.20211002183613-ada9ef6790c3/go.mod h1:4alQ3YuqEWAorEQ3Oz6ZqSdh6ZjIN/LEEC922dtMOhw=
github.com/rancher-sandbox/gofilecache v0.0.0-20210330135715-becdeff5df15 h1:w8tg3snxZF0UHTVmYq7DDPkC3lehwFC/4EwVTAxFeWg= github.com/rancher-sandbox/gofilecache v0.0.0-20210330135715-becdeff5df15 h1:w8tg3snxZF0UHTVmYq7DDPkC3lehwFC/4EwVTAxFeWg=
github.com/rancher-sandbox/gofilecache v0.0.0-20210330135715-becdeff5df15/go.mod h1:+Uhkjp4zCSryD4cpHhEu8uz4fIQ533t6Lv6M6pSVIKQ= github.com/rancher-sandbox/gofilecache v0.0.0-20210330135715-becdeff5df15/go.mod h1:+Uhkjp4zCSryD4cpHhEu8uz4fIQ533t6Lv6M6pSVIKQ=
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
github.com/remyoudompheng/bigfft v0.0.0-20170806203942-52369c62f446/go.mod h1:uYEyJGbgTkfkS4+E/PavXkNJcbFIpEtjt2B0KDQ5+9M= github.com/remyoudompheng/bigfft v0.0.0-20170806203942-52369c62f446/go.mod h1:uYEyJGbgTkfkS4+E/PavXkNJcbFIpEtjt2B0KDQ5+9M=
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/rogpeppe/fastuuid v1.1.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/fastuuid v1.1.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
@ -902,8 +907,6 @@ github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQD
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E=
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
github.com/schollz/progressbar/v3 v3.7.1 h1:aQR/t6d+1nURSdoMn6c7n0vJi5xQ3KndpF0n7R5wrik=
github.com/schollz/progressbar/v3 v3.7.1/go.mod h1:CG/f0JmacksUc6TkZToO7tVq4t03zIQSQUtTd7F9GR4=
github.com/sclevine/spec v1.2.0/go.mod h1:W4J29eT/Kzv7/b9IWLB055Z+qvVC9vt0Arko24q7p+U= github.com/sclevine/spec v1.2.0/go.mod h1:W4J29eT/Kzv7/b9IWLB055Z+qvVC9vt0Arko24q7p+U=
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
@ -1014,6 +1017,8 @@ github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17
github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/xlab/handysort v0.0.0-20150421192137-fb3537ed64a1/go.mod h1:QcJo0QPSfTONNIgpN5RA8prR7fF8nkF6cTWTcNerRO8= github.com/xlab/handysort v0.0.0-20150421192137-fb3537ed64a1/go.mod h1:QcJo0QPSfTONNIgpN5RA8prR7fF8nkF6cTWTcNerRO8=
github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 h1:QldyIu/L63oPpyvQmHgvgickp1Yw510KJOqX7H24mg8=
github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778/go.mod h1:2MuV+tbUrU1zIOPMxZ5EncGwgmMJsa+9ucAQZXxsObs=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
@ -1087,7 +1092,6 @@ golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPh
golang.org/x/crypto v0.0.0-20200414173820-0848c9571904/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200414173820-0848c9571904/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201112155050-0c6587e931a9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201117144127-c1f2f97bffc9/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20201117144127-c1f2f97bffc9/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 h1:/UOmuWzQfxxo9UtlXMwuQU8CMgg1eZXqTRwkSQJWKOI= golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 h1:/UOmuWzQfxxo9UtlXMwuQU8CMgg1eZXqTRwkSQJWKOI=
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
@ -1252,7 +1256,6 @@ golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200120151820-655fe14d7479/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200120151820-655fe14d7479/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@ -1271,7 +1274,6 @@ golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200922070232-aee5d888a860/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200922070232-aee5d888a860/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201113135734-0a15ea8d9b02/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@ -1288,11 +1290,15 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210915083310-ed5796bab164 h1:7ZDGnxgHAMw7thfC5bEos0RDAccZKxioiWBhfIe+tvw=
golang.org/x/sys v0.0.0-20210915083310-ed5796bab164/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210915083310-ed5796bab164/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654 h1:id054HUawV2/6IGm2IV8KZQjqtwAOo2CYlOToYqa0d0=
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=

View File

@ -18,8 +18,7 @@ package artifact_test
import ( import (
"testing" "testing"
. "github.com/mudler/luet/cmd" . "github.com/mudler/luet/cmd/util"
config "github.com/mudler/luet/pkg/config"
. "github.com/onsi/ginkgo" . "github.com/onsi/ginkgo"
. "github.com/onsi/gomega" . "github.com/onsi/gomega"
@ -27,6 +26,6 @@ import (
func TestArtifact(t *testing.T) { func TestArtifact(t *testing.T) {
RegisterFailHandler(Fail) RegisterFailHandler(Fail)
LoadConfig(config.LuetCfg) LoadConfig()
RunSpecs(t, "Artifact Suite") RunSpecs(t, "Artifact Suite")
} }

View File

@ -18,8 +18,7 @@ package types_test
import ( import (
"testing" "testing"
. "github.com/mudler/luet/cmd" . "github.com/mudler/luet/cmd/util"
config "github.com/mudler/luet/pkg/config"
. "github.com/onsi/ginkgo" . "github.com/onsi/ginkgo"
. "github.com/onsi/gomega" . "github.com/onsi/gomega"
@ -27,6 +26,6 @@ import (
func TestAPITypes(t *testing.T) { func TestAPITypes(t *testing.T) {
RegisterFailHandler(Fail) RegisterFailHandler(Fail)
LoadConfig(config.LuetCfg) LoadConfig()
RunSpecs(t, "Types Suite") RunSpecs(t, "Types Suite")
} }

View File

@ -18,8 +18,7 @@ package backend_test
import ( import (
"testing" "testing"
. "github.com/mudler/luet/cmd" . "github.com/mudler/luet/cmd/util"
config "github.com/mudler/luet/pkg/config"
. "github.com/onsi/ginkgo" . "github.com/onsi/ginkgo"
. "github.com/onsi/gomega" . "github.com/onsi/gomega"
@ -27,6 +26,6 @@ import (
func TestSolver(t *testing.T) { func TestSolver(t *testing.T) {
RegisterFailHandler(Fail) RegisterFailHandler(Fail)
LoadConfig(config.LuetCfg) LoadConfig()
RunSpecs(t, "Backend Suite") RunSpecs(t, "Backend Suite")
} }

View File

@ -53,7 +53,7 @@ func runCommand(cmd *exec.Cmd) error {
cmd.Stderr = writer cmd.Stderr = writer
if buffered { if buffered {
Spinner(22) Spinner(32)
defer SpinnerStop() defer SpinnerStop()
} }

View File

@ -29,7 +29,6 @@ import (
"sync" "sync"
"time" "time"
"github.com/imdario/mergo"
artifact "github.com/mudler/luet/pkg/api/core/types/artifact" artifact "github.com/mudler/luet/pkg/api/core/types/artifact"
bus "github.com/mudler/luet/pkg/bus" bus "github.com/mudler/luet/pkg/bus"
"github.com/mudler/luet/pkg/compiler/backend" "github.com/mudler/luet/pkg/compiler/backend"
@ -40,6 +39,8 @@ import (
. "github.com/mudler/luet/pkg/logger" . "github.com/mudler/luet/pkg/logger"
pkg "github.com/mudler/luet/pkg/package" pkg "github.com/mudler/luet/pkg/package"
"github.com/mudler/luet/pkg/solver" "github.com/mudler/luet/pkg/solver"
"github.com/imdario/mergo"
"github.com/pkg/errors" "github.com/pkg/errors"
"gopkg.in/yaml.v2" "gopkg.in/yaml.v2"
"helm.sh/helm/v3/pkg/chart" "helm.sh/helm/v3/pkg/chart"
@ -486,7 +487,7 @@ func (cs *LuetCompiler) waitForImages(images []string) {
available, _ := oneOfImagesAvailable(images, cs.Backend) available, _ := oneOfImagesAvailable(images, cs.Backend)
if !available { if !available {
Info(fmt.Sprintf("Waiting for image %s to be available... :zzz:", images)) Info(fmt.Sprintf("Waiting for image %s to be available... :zzz:", images))
Spinner(22) Spinner(32)
defer SpinnerStop() defer SpinnerStop()
for !available { for !available {
available, _ = oneOfImagesAvailable(images, cs.Backend) available, _ = oneOfImagesAvailable(images, cs.Backend)

View File

@ -18,8 +18,7 @@ package compiler_test
import ( import (
"testing" "testing"
. "github.com/mudler/luet/cmd" . "github.com/mudler/luet/cmd/util"
config "github.com/mudler/luet/pkg/config"
. "github.com/onsi/ginkgo" . "github.com/onsi/ginkgo"
. "github.com/onsi/gomega" . "github.com/onsi/gomega"
@ -27,6 +26,6 @@ import (
func TestSolver(t *testing.T) { func TestSolver(t *testing.T) {
RegisterFailHandler(Fail) RegisterFailHandler(Fail)
LoadConfig(config.LuetCfg) LoadConfig()
RunSpecs(t, "Compiler Suite") RunSpecs(t, "Compiler Suite")
} }

View File

@ -18,8 +18,7 @@ package compilerspec_test
import ( import (
"testing" "testing"
. "github.com/mudler/luet/cmd" . "github.com/mudler/luet/cmd/util"
config "github.com/mudler/luet/pkg/config"
. "github.com/onsi/ginkgo" . "github.com/onsi/ginkgo"
. "github.com/onsi/gomega" . "github.com/onsi/gomega"
@ -27,6 +26,6 @@ import (
func TestSpec(t *testing.T) { func TestSpec(t *testing.T) {
RegisterFailHandler(Fail) RegisterFailHandler(Fail)
LoadConfig(config.LuetCfg) LoadConfig()
RunSpecs(t, "Spec Suite") RunSpecs(t, "Spec Suite")
} }

View File

@ -1,5 +1,6 @@
// Copyright © 2019 Ettore Di Giacinto <mudler@gentoo.org> // Copyright © 2019 Ettore Di Giacinto <mudler@gentoo.org>
// Daniele Rondina <geaaru@sabayonlinux.org> // Daniele Rondina <geaaru@sabayonlinux.org>
// 2021 Ettore Di Giacinto <mudler@mocaccino.org>
// //
// This program is free software; you can redistribute it and/or modify // This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
@ -20,9 +21,7 @@ import (
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"os" "os"
"os/user"
"path/filepath" "path/filepath"
"runtime"
"strings" "strings"
"time" "time"
@ -32,11 +31,10 @@ import (
solver "github.com/mudler/luet/pkg/solver" solver "github.com/mudler/luet/pkg/solver"
"github.com/pkg/errors" "github.com/pkg/errors"
v "github.com/spf13/viper"
"gopkg.in/yaml.v2" "gopkg.in/yaml.v2"
) )
var LuetCfg = NewLuetConfig(v.GetViper()) var LuetCfg = &LuetConfig{}
var AvailableResolvers = strings.Join([]string{solver.QLearningResolverType}, " ") var AvailableResolvers = strings.Join([]string{solver.QLearningResolverType}, " ")
type LuetLoggingConfig struct { type LuetLoggingConfig struct {
@ -162,15 +160,12 @@ func (sc *LuetSystemConfig) GetRootFsAbs() (string, error) {
return filepath.Abs(sc.Rootfs) return filepath.Abs(sc.Rootfs)
} }
type LuetKV struct { type LuetKV struct {
Key string `json:"key" yaml:"key" mapstructure:"key"` Key string `json:"key" yaml:"key" mapstructure:"key"`
Value string `json:"value" yaml:"value" mapstructure:"value"` Value string `json:"value" yaml:"value" mapstructure:"value"`
} }
type LuetConfig struct { type LuetConfig struct {
Viper *v.Viper `yaml:"-"`
Logging LuetLoggingConfig `yaml:"logging,omitempty" mapstructure:"logging"` Logging LuetLoggingConfig `yaml:"logging,omitempty" mapstructure:"logging"`
General LuetGeneralConfig `yaml:"general,omitempty" mapstructure:"general"` General LuetGeneralConfig `yaml:"general,omitempty" mapstructure:"general"`
System LuetSystemConfig `yaml:"system" mapstructure:"system"` System LuetSystemConfig `yaml:"system" mapstructure:"system"`
@ -187,59 +182,6 @@ type LuetConfig struct {
ConfigProtectConfFiles []ConfigProtectConfFile `yaml:"-" mapstructure:"-"` ConfigProtectConfFiles []ConfigProtectConfFile `yaml:"-" mapstructure:"-"`
} }
func NewLuetConfig(viper *v.Viper) *LuetConfig {
if viper == nil {
viper = v.New()
}
GenDefault(viper)
return &LuetConfig{Viper: viper, ConfigProtectConfFiles: nil}
}
func GenDefault(viper *v.Viper) {
viper.SetDefault("logging.level", "info")
viper.SetDefault("logging.enable_logfile", false)
viper.SetDefault("logging.path", "/var/log/luet.log")
viper.SetDefault("logging.json_format", false)
viper.SetDefault("logging.enable_emoji", true)
viper.SetDefault("logging.color", true)
viper.SetDefault("general.concurrency", runtime.NumCPU())
viper.SetDefault("general.debug", false)
viper.SetDefault("general.show_build_output", false)
viper.SetDefault("general.spinner_ms", 100)
viper.SetDefault("general.spinner_charset", 22)
viper.SetDefault("general.fatal_warnings", false)
u, err := user.Current()
// os/user doesn't work in from scratch environments
if err != nil || (u != nil && u.Uid == "0") {
viper.SetDefault("general.same_owner", true)
} else {
viper.SetDefault("general.same_owner", false)
}
viper.SetDefault("system.database_engine", "boltdb")
viper.SetDefault("system.database_path", "/var/cache/luet")
viper.SetDefault("system.rootfs", "/")
viper.SetDefault("system.tmpdir_base", filepath.Join(os.TempDir(), "tmpluet"))
viper.SetDefault("system.pkgs_cache_path", "packages")
viper.SetDefault("repos_confdir", []string{"/etc/luet/repos.conf.d"})
viper.SetDefault("config_protect_confdir", []string{"/etc/luet/config.protect.d"})
viper.SetDefault("config_protect_skip", false)
// TODO: Set default to false when we are ready for migration.
viper.SetDefault("config_from_host", true)
viper.SetDefault("cache_repositories", []string{})
viper.SetDefault("system_repositories", []string{})
viper.SetDefault("finalizer_envs", make(map[string]string, 0))
viper.SetDefault("solver.type", "")
viper.SetDefault("solver.rate", 0.7)
viper.SetDefault("solver.discount", 1.0)
viper.SetDefault("solver.max_attempts", 9000)
}
func (c *LuetConfig) GetSystemDB() pkg.PackageDatabase { func (c *LuetConfig) GetSystemDB() pkg.PackageDatabase {
switch LuetCfg.GetSystem().DatabaseEngine { switch LuetCfg.GetSystem().DatabaseEngine {
case "boltdb": case "boltdb":

View File

@ -19,8 +19,7 @@ package config_test
import ( import (
"testing" "testing"
. "github.com/mudler/luet/cmd" . "github.com/mudler/luet/cmd/util"
config "github.com/mudler/luet/pkg/config"
. "github.com/onsi/ginkgo" . "github.com/onsi/ginkgo"
. "github.com/onsi/gomega" . "github.com/onsi/gomega"
@ -28,6 +27,6 @@ import (
func TestSolver(t *testing.T) { func TestSolver(t *testing.T) {
RegisterFailHandler(Fail) RegisterFailHandler(Fail)
LoadConfig(config.LuetCfg) LoadConfig()
RunSpecs(t, "Config Suite") RunSpecs(t, "Config Suite")
} }

View File

@ -18,8 +18,7 @@ package helpers_test
import ( import (
"testing" "testing"
. "github.com/mudler/luet/cmd" . "github.com/mudler/luet/cmd/util"
config "github.com/mudler/luet/pkg/config"
. "github.com/onsi/ginkgo" . "github.com/onsi/ginkgo"
. "github.com/onsi/gomega" . "github.com/onsi/gomega"
@ -27,6 +26,6 @@ import (
func TestSolver(t *testing.T) { func TestSolver(t *testing.T) {
RegisterFailHandler(Fail) RegisterFailHandler(Fail)
LoadConfig(config.LuetCfg) LoadConfig()
RunSpecs(t, "Helpers Suite") RunSpecs(t, "Helpers Suite")
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,27 @@
// +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
}

97
pkg/installer/cli.go Normal file
View File

@ -0,0 +1,97 @@
// Copyright © 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
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, see <http://www.gnu.org/licenses/>.
package installer
import (
"fmt"
"sort"
"strings"
pkg "github.com/mudler/luet/pkg/package"
"github.com/pterm/pterm"
)
func packsToList(p pkg.Packages) string {
var packs []string
for _, pp := range p {
packs = append(packs, pp.HumanReadableString())
}
sort.Strings(packs)
return strings.Join(packs, " ")
}
func printList(p pkg.Packages) {
d := pterm.TableData{{"Program Name", "Version", "License"}}
for _, m := range p {
d = append(d, []string{
fmt.Sprintf("%s/%s", m.GetCategory(), m.GetName()),
pterm.LightGreen(m.GetVersion()), m.GetLicense()})
}
pterm.DefaultTable.WithHasHeader().WithData(d).Render()
}
func printUpgradeList(install, uninstall pkg.Packages) {
d := pterm.TableData{{"Old version", "New version", "License"}}
for _, m := range uninstall {
if p, err := install.Find(m.GetPackageName()); err == nil {
d = append(d, []string{
pterm.LightRed(m.HumanReadableString()),
pterm.LightGreen(p.HumanReadableString()), m.GetLicense()})
} else {
d = append(d, []string{
pterm.LightRed(m.HumanReadableString()), ""})
}
}
for _, m := range install {
if _, err := uninstall.Find(m.GetPackageName()); err != nil {
d = append(d, []string{"",
pterm.LightGreen(m.HumanReadableString()), m.GetLicense()})
}
}
pterm.DefaultTable.WithHasHeader().WithData(d).Render()
}
func printMatchUpgrade(artefacts map[string]ArtifactMatch, uninstall pkg.Packages) {
p := pkg.Packages{}
for _, a := range artefacts {
p = append(p, a.Package)
}
printUpgradeList(p, uninstall)
}
func printMatches(artefacts map[string]ArtifactMatch) {
d := pterm.TableData{{"Program Name", "Version", "License", "Repository"}}
for _, m := range artefacts {
d = append(d, []string{
fmt.Sprintf("%s/%s", m.Package.GetCategory(), m.Package.GetName()),
pterm.LightGreen(m.Package.GetVersion()), m.Package.GetLicense(), m.Repository.Name})
}
pterm.DefaultTable.WithHasHeader().WithData(d).Render()
}
func matchesToList(artefacts map[string]ArtifactMatch) string {
var packs []string
for fingerprint, match := range artefacts {
packs = append(packs, fmt.Sprintf("%s (%s)", fingerprint, match.Repository.GetName()))
}
sort.Strings(packs)
return strings.Join(packs, " ")
}

View File

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

View File

@ -29,16 +29,17 @@ import (
"github.com/mudler/luet/pkg/api/core/types/artifact" "github.com/mudler/luet/pkg/api/core/types/artifact"
. "github.com/mudler/luet/pkg/logger" . "github.com/mudler/luet/pkg/logger"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/pterm/pterm"
"github.com/cavaliercoder/grab" "github.com/cavaliercoder/grab"
"github.com/mudler/luet/pkg/config" "github.com/mudler/luet/pkg/config"
"github.com/schollz/progressbar/v3"
) )
type HttpClient struct { type HttpClient struct {
RepoData RepoData RepoData RepoData
Cache *artifact.ArtifactCache Cache *artifact.ArtifactCache
ProgressBarArea *pterm.AreaPrinter
} }
func NewHttpClient(r RepoData) *HttpClient { func NewHttpClient(r RepoData) *HttpClient {
@ -124,28 +125,11 @@ func (c *HttpClient) DownloadFile(p string) (string, error) {
} }
resp := client.Do(req) resp := client.Do(req)
pb := pterm.DefaultProgressbar.WithTotal(int(resp.Size()))
bar := progressbar.NewOptions64( if c.ProgressBarArea != nil {
resp.Size(), pb = pb.WithPrintTogether(c.ProgressBarArea)
progressbar.OptionSetDescription( }
fmt.Sprintf("[cyan] %s - [reset]", pb, _ = pb.WithTitle(filepath.Base(resp.Request.HTTPRequest.URL.RequestURI())).Start()
filepath.Base(resp.Request.HTTPRequest.URL.RequestURI()))),
progressbar.OptionSetRenderBlankState(true),
progressbar.OptionEnableColorCodes(config.LuetCfg.GetLogging().Color),
progressbar.OptionClearOnFinish(),
progressbar.OptionShowBytes(true),
progressbar.OptionShowCount(),
progressbar.OptionSetPredictTime(true),
progressbar.OptionFullWidth(),
progressbar.OptionSetTheme(progressbar.Theme{
Saucer: "[white]=[reset]",
SaucerHead: "[white]>[reset]",
SaucerPadding: " ",
BarStart: "[",
BarEnd: "]",
}))
bar.Reset()
// start download loop // start download loop
t := time.NewTicker(500 * time.Millisecond) t := time.NewTicker(500 * time.Millisecond)
defer t.Stop() defer t.Stop()
@ -155,8 +139,9 @@ func (c *HttpClient) DownloadFile(p string) (string, error) {
for { for {
select { select {
case <-t.C: case <-t.C:
bar.Set64(resp.BytesComplete()) // bar.Set64(resp.BytesComplete())
//pb.Increment()
pb.Increment().Current = int(resp.BytesComplete())
case <-resp.Done: case <-resp.Done:
// download is complete // download is complete
break download_loop break download_loop
@ -167,11 +152,11 @@ func (c *HttpClient) DownloadFile(p string) (string, error) {
continue continue
} }
Info("\nDownloaded", p, "of", Info("Downloaded", p, "of",
fmt.Sprintf("%.2f", (float64(resp.BytesComplete())/1000)/1000), "MB (", fmt.Sprintf("%.2f", (float64(resp.BytesComplete())/1000)/1000), "MB (",
fmt.Sprintf("%.2f", (float64(resp.BytesPerSecond())/1024)/1024), "MiB/s )") fmt.Sprintf("%.2f", (float64(resp.BytesPerSecond())/1024)/1024), "MiB/s )")
pb.Stop()
bar.Finish() //bar.Finish()
downloaded = true downloaded = true
break break
} }

View File

@ -31,11 +31,12 @@ import (
"github.com/mudler/luet/pkg/helpers" "github.com/mudler/luet/pkg/helpers"
fileHelper "github.com/mudler/luet/pkg/helpers/file" fileHelper "github.com/mudler/luet/pkg/helpers/file"
"github.com/mudler/luet/pkg/helpers/match" "github.com/mudler/luet/pkg/helpers/match"
"github.com/mudler/luet/pkg/installer/client"
. "github.com/mudler/luet/pkg/logger" . "github.com/mudler/luet/pkg/logger"
pkg "github.com/mudler/luet/pkg/package" pkg "github.com/mudler/luet/pkg/package"
"github.com/mudler/luet/pkg/solver" "github.com/mudler/luet/pkg/solver"
"github.com/pterm/pterm"
. "github.com/logrusorgru/aurora"
"github.com/pkg/errors" "github.com/pkg/errors"
) )
@ -124,27 +125,6 @@ func (l *LuetInstaller) computeUpgrade(syncedRepos Repositories, s *System) (pkg
return uninstall, toInstall, nil return uninstall, toInstall, nil
} }
func packsToList(p pkg.Packages) string {
var packs []string
for _, pp := range p {
packs = append(packs, pp.HumanReadableString())
}
sort.Strings(packs)
return strings.Join(packs, " ")
}
func matchesToList(artefacts map[string]ArtifactMatch) string {
var packs []string
for fingerprint, match := range artefacts {
packs = append(packs, fmt.Sprintf("%s (%s)", fingerprint, match.Repository.GetName()))
}
sort.Strings(packs)
return strings.Join(packs, " ")
}
// Upgrade upgrades a System based on the Installer options. Returns error in case of failure // Upgrade upgrades a System based on the Installer options. Returns error in case of failure
func (l *LuetInstaller) Upgrade(s *System) error { func (l *LuetInstaller) Upgrade(s *System) error {
@ -249,13 +229,17 @@ func (l *LuetInstaller) swap(o Option, syncedRepos Repositories, toRemove pkg.Pa
} }
if l.Options.Ask { if l.Options.Ask {
if len(toRemove) > 0 { // if len(toRemove) > 0 {
Info(":recycle: Packages that are going to be removed from the system:\n ", Yellow(packsToList(toRemove)).BgBlack().String()) // Info(":recycle: Packages that are going to be removed from the system:\n ", Yellow(packsToList(toRemove)).BgBlack().String())
} // }
if len(match) > 0 { // if len(match) > 0 {
Info("Packages that are going to be installed in the system: \n ", Green(matchesToList(match)).BgBlack().String()) // Info("Packages that are going to be installed in the system:")
} // // Info("Packages that are going to be installed in the system: \n ", Green(matchesToList(match)).BgBlack().String())
// printMatches(match)
// }
Info(":zap: Proposed version changes to the system:\n ")
printMatchUpgrade(match, toRemove)
Info("By going forward, you are also accepting the licenses of the packages that you are going to install in your system.") Info("By going forward, you are also accepting the licenses of the packages that you are going to install in your system.")
if Ask() { if Ask() {
@ -455,24 +439,19 @@ func (l *LuetInstaller) getOpsWithOptions(
} }
func (l *LuetInstaller) checkAndUpgrade(r Repositories, s *System) error { func (l *LuetInstaller) checkAndUpgrade(r Repositories, s *System) error {
Spinner(32) // Spinner(32)
uninstall, toInstall, err := l.computeUpgrade(r, s) uninstall, toInstall, err := l.computeUpgrade(r, s)
if err != nil { if err != nil {
return errors.Wrap(err, "failed computing upgrade") return errors.Wrap(err, "failed computing upgrade")
} }
SpinnerStop() // SpinnerStop()
if len(uninstall) > 0 {
Info(":recycle: Packages that are going to be removed from the system:\n ", Yellow(packsToList(uninstall)).BgBlack().String())
}
if len(toInstall) > 0 {
Info(":zap:Packages that are going to be installed in the system:\n ", Green(packsToList(toInstall)).BgBlack().String())
}
if len(toInstall) == 0 && len(uninstall) == 0 { if len(toInstall) == 0 && len(uninstall) == 0 {
Info("Nothing to do") Info("Nothing to upgrade")
return nil return nil
} else {
Info(":zap: Proposed version changes to the system:\n ")
printUpgradeList(toInstall, uninstall)
} }
// We don't want any conflict with the installed to raise during the upgrade. // We don't want any conflict with the installed to raise during the upgrade.
@ -505,6 +484,7 @@ func (l *LuetInstaller) checkAndUpgrade(r Repositories, s *System) error {
} }
func (l *LuetInstaller) Install(cp pkg.Packages, s *System) error { func (l *LuetInstaller) Install(cp pkg.Packages, s *System) error {
Screen("Install")
syncedRepos, err := l.SyncRepositories() syncedRepos, err := l.SyncRepositories()
if err != nil { if err != nil {
return err return err
@ -560,7 +540,10 @@ func (l *LuetInstaller) Install(cp pkg.Packages, s *System) error {
} }
} }
} }
Info("Packages that are going to be installed in the system: \n ", Green(matchesToList(match)).BgBlack().String()) Info("Packages that are going to be installed in the system:")
//Info("Packages that are going to be installed in the system: \n ", Green(matchesToList(match)).BgBlack().String())
printMatches(match)
if l.Options.Ask { if l.Options.Ask {
Info("By going forward, you are also accepting the licenses of the packages that you are going to install in your system.") Info("By going forward, you are also accepting the licenses of the packages that you are going to install in your system.")
@ -581,16 +564,21 @@ func (l *LuetInstaller) download(syncedRepos Repositories, toDownload map[string
var wg = new(sync.WaitGroup) var wg = new(sync.WaitGroup)
area, _ := pterm.DefaultArea.Start()
p, _ := pterm.DefaultProgressbar.WithPrintTogether(area).WithTotal(len(toDownload)).WithTitle("Downloading packages").Start()
// Download // Download
for i := 0; i < l.Options.Concurrency; i++ { for i := 0; i < l.Options.Concurrency; i++ {
wg.Add(1) wg.Add(1)
go l.downloadWorker(i, wg, all) go l.downloadWorker(i, wg, all, p, area)
} }
for _, c := range toDownload { for _, c := range toDownload {
all <- c all <- c
} }
close(all) close(all)
wg.Wait() wg.Wait()
area.Stop()
return nil return nil
} }
@ -782,7 +770,7 @@ func (l *LuetInstaller) checkFileconflicts(toInstall map[string]ArtifactMatch, c
filesToInstall := []string{} filesToInstall := []string{}
for _, m := range toInstall { for _, m := range toInstall {
a, err := l.downloadPackage(m) a, err := l.downloadPackage(m, nil)
if err != nil && !l.Options.Force { if err != nil && !l.Options.Force {
return errors.Wrap(err, "Failed downloading package") return errors.Wrap(err, "Failed downloading package")
} }
@ -877,9 +865,16 @@ func (l *LuetInstaller) install(o Option, syncedRepos Repositories, toInstall ma
return s.ExecuteFinalizers(toFinalize) return s.ExecuteFinalizers(toFinalize)
} }
func (l *LuetInstaller) downloadPackage(a ArtifactMatch) (*artifact.PackageArtifact, error) { func (l *LuetInstaller) downloadPackage(a ArtifactMatch, area *pterm.AreaPrinter) (*artifact.PackageArtifact, error) {
artifact, err := a.Repository.Client().DownloadArtifact(a.Artifact) cli := a.Repository.Client()
switch v := cli.(type) {
case *client.HttpClient:
v.ProgressBarArea = area
}
artifact, err := cli.DownloadArtifact(a.Artifact)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "Error on download artifact") return nil, errors.Wrap(err, "Error on download artifact")
} }
@ -893,7 +888,7 @@ func (l *LuetInstaller) downloadPackage(a ArtifactMatch) (*artifact.PackageArtif
func (l *LuetInstaller) installPackage(m ArtifactMatch, s *System) error { func (l *LuetInstaller) installPackage(m ArtifactMatch, s *System) error {
a, err := l.downloadPackage(m) a, err := l.downloadPackage(m, nil)
if err != nil && !l.Options.Force { if err != nil && !l.Options.Force {
return errors.Wrap(err, "Failed downloading package") return errors.Wrap(err, "Failed downloading package")
} }
@ -913,18 +908,20 @@ func (l *LuetInstaller) installPackage(m ArtifactMatch, s *System) error {
return s.Database.SetPackageFiles(&pkg.PackageFile{PackageFingerprint: m.Package.GetFingerPrint(), Files: files}) return s.Database.SetPackageFiles(&pkg.PackageFile{PackageFingerprint: m.Package.GetFingerPrint(), Files: files})
} }
func (l *LuetInstaller) downloadWorker(i int, wg *sync.WaitGroup, c <-chan ArtifactMatch) error { func (l *LuetInstaller) downloadWorker(i int, wg *sync.WaitGroup, c <-chan ArtifactMatch, pb *pterm.ProgressbarPrinter, area *pterm.AreaPrinter) error {
defer wg.Done() defer wg.Done()
for p := range c { for p := range c {
// TODO: Keep trace of what was added from the tar, and save it into system // TODO: Keep trace of what was added from the tar, and save it into system
_, err := l.downloadPackage(p) _, err := l.downloadPackage(p, area)
if err != nil { if err != nil {
Fatal("Failed downloading package "+p.Package.GetName(), err.Error()) Error("Failed downloading package "+p.Package.GetName(), err.Error())
return errors.Wrap(err, "Failed downloading package "+p.Package.GetName()) return errors.Wrap(err, "Failed downloading package "+p.Package.GetName())
} else { } else {
Info(":package: Package ", p.Package.HumanReadableString(), "downloaded") Success(":package: Package ", p.Package.HumanReadableString(), "downloaded")
} }
pb.Increment()
} }
return nil return nil
@ -1183,7 +1180,8 @@ func (l *LuetInstaller) Uninstall(s *System, packs ...pkg.Package) error {
} }
if l.Options.Ask { if l.Options.Ask {
Info(":recycle: Packages that are going to be removed from the system:\n ", Yellow(packsToList(toUninstall)).BgBlack().String()) Info(":recycle: Packages that are going to be removed from the system:")
printList(toUninstall)
if Ask() { if Ask() {
l.Options.Ask = false // Don't prompt anymore l.Options.Ask = false // Don't prompt anymore
return uninstall() return uninstall()

View File

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

View File

@ -9,24 +9,24 @@ import (
"strings" "strings"
"sync" "sync"
. "github.com/mudler/luet/pkg/config" . "github.com/mudler/luet/pkg/config"
"github.com/briandowns/spinner"
"github.com/kyokomi/emoji" "github.com/kyokomi/emoji"
. "github.com/logrusorgru/aurora" . "github.com/logrusorgru/aurora"
"github.com/pterm/pterm"
"go.uber.org/zap" "go.uber.org/zap"
"go.uber.org/zap/zapcore" "go.uber.org/zap/zapcore"
) )
var s *spinner.Spinner = nil var s *pterm.SpinnerPrinter
var z *zap.Logger = nil var z *zap.Logger = nil
var aurora Aurora = nil var aurora Aurora = nil
var spinnerLock = sync.Mutex{} var spinnerLock = sync.Mutex{}
func NewSpinner() { func NewSpinner() {
if s == nil { if s == nil {
s = spinner.New( s = pterm.DefaultSpinner.WithShowTimer(false).WithRemoveWhenDone(true)
spinner.CharSets[LuetCfg.GetGeneral().SpinnerCharset],
LuetCfg.GetGeneral().GetSpinnerMs())
} }
} }
@ -40,6 +40,10 @@ func GetAurora() Aurora {
return aurora return aurora
} }
func NoColor() {
pterm.DisableColor()
}
func Ask() bool { func Ask() bool {
var input string var input string
@ -100,24 +104,41 @@ func Spinner(i int) {
i = 43 i = 43
} }
if s != nil && !s.Active() { if s != nil && !s.IsActive {
// s.UpdateCharSet(spinner.CharSets[i]) // s.UpdateCharSet(spinner.CharSets[i])
s.Start() // Start the spinner //s.Start() // Start the spinner
// time.Sleep(second)
// for i := 14; i > 0; i-- {
// if i > 1 {
// introSpinner.UpdateText("Waiting for " + strconv.Itoa(i) + " seconds...")
// } else {
// introSpinner.UpdateText("Waiting for " + strconv.Itoa(i) + " second...")
// }
// time.Sleep(second)
// }
// s = introSpinner
s, _ = s.Start()
//introSpinner.Stop()
} }
} }
func Screen(text string) {
pterm.DefaultHeader.WithBackgroundStyle(pterm.NewStyle(pterm.BgLightBlue)).WithMargin(2).Println(text)
//pterm.DefaultCenter.Print(pterm.DefaultHeader.WithFullWidth().WithBackgroundStyle(pterm.NewStyle(pterm.BgLightBlue)).WithMargin(10).Sprint(text))
}
func SpinnerText(suffix, prefix string) { func SpinnerText(suffix, prefix string) {
if s != nil { if s != nil {
s.Lock() spinnerLock.Lock()
defer s.Unlock() defer spinnerLock.Unlock()
if LuetCfg.GetGeneral().Debug { if LuetCfg.GetGeneral().Debug {
fmt.Println(fmt.Sprintf("%s %s", fmt.Println(fmt.Sprintf("%s %s",
Bold(Cyan(prefix)).String(), Bold(Cyan(prefix)).String(),
Bold(Magenta(suffix)).BgBlack().String(), Bold(Magenta(suffix)).BgBlack().String(),
)) ))
} else { } else {
s.Suffix = Bold(Magenta(suffix)).BgBlack().String() s.UpdateText(suffix + prefix)
s.Prefix = Bold(Cyan(prefix)).String()
} }
} }
} }
@ -135,7 +156,7 @@ func SpinnerStop() {
return return
} }
if s != nil { if s != nil {
s.Stop() s.Success()
} }
} }
@ -147,8 +168,10 @@ func level2Number(level string) int {
return 1 return 1
case "info": case "info":
return 2 return 2
default: case "success":
return 3 return 3
default:
return 4
} }
} }
@ -158,7 +181,7 @@ func log2File(level, msg string) {
z.Error(msg) z.Error(msg)
case "warning": case "warning":
z.Warn(msg) z.Warn(msg)
case "info": case "info", "success":
z.Info(msg) z.Info(msg)
default: default:
z.Debug(msg) z.Debug(msg)
@ -171,13 +194,17 @@ func level2AtomicLevel(level string) zap.AtomicLevel {
return zap.NewAtomicLevelAt(zap.ErrorLevel) return zap.NewAtomicLevelAt(zap.ErrorLevel)
case "warning": case "warning":
return zap.NewAtomicLevelAt(zap.WarnLevel) return zap.NewAtomicLevelAt(zap.WarnLevel)
case "info": case "info", "success":
return zap.NewAtomicLevelAt(zap.InfoLevel) return zap.NewAtomicLevelAt(zap.InfoLevel)
default: default:
return zap.NewAtomicLevelAt(zap.DebugLevel) return zap.NewAtomicLevelAt(zap.DebugLevel)
} }
} }
func init() {
InitAurora()
}
func Msg(level string, withoutColor, ln bool, msg ...interface{}) { func Msg(level string, withoutColor, ln bool, msg ...interface{}) {
var message string var message string
var confLevel, msgLevel int var confLevel, msgLevel int
@ -206,7 +233,7 @@ func Msg(level string, withoutColor, ln bool, msg ...interface{}) {
levelMsg = Yellow(":construction: warning" + message).BgBlack().String() levelMsg = Yellow(":construction: warning" + message).BgBlack().String()
case "debug": case "debug":
levelMsg = White(message).BgBlack().String() levelMsg = White(message).BgBlack().String()
case "info": case "info", "success":
levelMsg = message levelMsg = message
case "error": case "error":
levelMsg = Red(message).String() levelMsg = Red(message).String()
@ -225,13 +252,41 @@ func Msg(level string, withoutColor, ln bool, msg ...interface{}) {
} }
if ln { if ln {
switch level {
case "info":
pterm.Info.Println(levelMsg)
case "success":
pterm.Success.Println(levelMsg)
case "warning":
pterm.Warning.Println(levelMsg)
case "error":
pterm.Error.Println(levelMsg)
case "fatal":
pterm.Fatal.Println(levelMsg)
default:
fmt.Println(levelMsg) fmt.Println(levelMsg)
}
//
} else { } else {
switch level {
case "success":
pterm.Success.Print(levelMsg)
case "info":
pterm.Info.Print(levelMsg)
case "warning":
pterm.Warning.Print(levelMsg)
case "error":
pterm.Error.Print(levelMsg)
case "fatal":
pterm.Fatal.Print(levelMsg)
default:
fmt.Print(levelMsg) fmt.Print(levelMsg)
} }
} }
}
func Warning(mess ...interface{}) { func Warning(mess ...interface{}) {
Msg("warning", false, true, mess...) Msg("warning", false, true, mess...)
if LuetCfg.GetGeneral().FatalWarns { if LuetCfg.GetGeneral().FatalWarns {
@ -256,6 +311,10 @@ func Info(mess ...interface{}) {
Msg("info", false, true, mess...) Msg("info", false, true, mess...)
} }
func Success(mess ...interface{}) {
Msg("success", false, true, mess...)
}
func InfoC(mess ...interface{}) { func InfoC(mess ...interface{}) {
Msg("info", true, true, mess...) Msg("info", true, true, mess...)
} }

View File

@ -18,8 +18,7 @@ package pkg_test
import ( import (
"testing" "testing"
. "github.com/mudler/luet/cmd" . "github.com/mudler/luet/cmd/util"
config "github.com/mudler/luet/pkg/config"
. "github.com/onsi/ginkgo" . "github.com/onsi/ginkgo"
. "github.com/onsi/gomega" . "github.com/onsi/gomega"
@ -27,6 +26,6 @@ import (
func TestSolver(t *testing.T) { func TestSolver(t *testing.T) {
RegisterFailHandler(Fail) RegisterFailHandler(Fail)
LoadConfig(config.LuetCfg) LoadConfig()
RunSpecs(t, "Package Suite") RunSpecs(t, "Package Suite")
} }

View File

@ -19,8 +19,7 @@ package repository_test
import ( import (
"testing" "testing"
. "github.com/mudler/luet/cmd" . "github.com/mudler/luet/cmd/util"
config "github.com/mudler/luet/pkg/config"
. "github.com/onsi/ginkgo" . "github.com/onsi/ginkgo"
. "github.com/onsi/gomega" . "github.com/onsi/gomega"
@ -28,6 +27,6 @@ import (
func TestSolver(t *testing.T) { func TestSolver(t *testing.T) {
RegisterFailHandler(Fail) RegisterFailHandler(Fail)
LoadConfig(config.LuetCfg) LoadConfig()
RunSpecs(t, "Repository Suite") RunSpecs(t, "Repository Suite")
} }

View File

@ -22,12 +22,11 @@ import (
. "github.com/onsi/ginkgo" . "github.com/onsi/ginkgo"
. "github.com/onsi/gomega" . "github.com/onsi/gomega"
viper "github.com/spf13/viper"
) )
var _ = Describe("Repository", func() { var _ = Describe("Repository", func() {
Context("Load Repository1", func() { Context("Load Repository1", func() {
cfg := NewLuetConfig(viper.New()) cfg := &LuetConfig{}
cfg.RepositoriesConfDir = []string{ cfg.RepositoriesConfDir = []string{
"../../tests/fixtures/repos.conf.d", "../../tests/fixtures/repos.conf.d",
} }

View File

@ -18,8 +18,7 @@ package solver_test
import ( import (
"testing" "testing"
. "github.com/mudler/luet/cmd" . "github.com/mudler/luet/cmd/util"
config "github.com/mudler/luet/pkg/config"
. "github.com/onsi/ginkgo" . "github.com/onsi/ginkgo"
. "github.com/onsi/gomega" . "github.com/onsi/gomega"
@ -27,6 +26,6 @@ import (
func TestSolver(t *testing.T) { func TestSolver(t *testing.T) {
RegisterFailHandler(Fail) RegisterFailHandler(Fail)
LoadConfig(config.LuetCfg) LoadConfig()
RunSpecs(t, "Solver Suite") RunSpecs(t, "Solver Suite")
} }

View File

@ -19,8 +19,7 @@ package spectooling_test
import ( import (
"testing" "testing"
. "github.com/mudler/luet/cmd" . "github.com/mudler/luet/cmd/util"
config "github.com/mudler/luet/pkg/config"
. "github.com/onsi/ginkgo" . "github.com/onsi/ginkgo"
. "github.com/onsi/gomega" . "github.com/onsi/gomega"
@ -28,6 +27,6 @@ import (
func TestSolver(t *testing.T) { func TestSolver(t *testing.T) {
RegisterFailHandler(Fail) RegisterFailHandler(Fail)
LoadConfig(config.LuetCfg) LoadConfig()
RunSpecs(t, "Spec Tooling Suite") RunSpecs(t, "Spec Tooling Suite")
} }

View File

@ -18,8 +18,7 @@ package tree_test
import ( import (
"testing" "testing"
. "github.com/mudler/luet/cmd" . "github.com/mudler/luet/cmd/util"
config "github.com/mudler/luet/pkg/config"
. "github.com/onsi/ginkgo" . "github.com/onsi/ginkgo"
. "github.com/onsi/gomega" . "github.com/onsi/gomega"
@ -27,6 +26,6 @@ import (
func TestTree(t *testing.T) { func TestTree(t *testing.T) {
RegisterFailHandler(Fail) RegisterFailHandler(Fail)
LoadConfig(config.LuetCfg) LoadConfig()
RunSpecs(t, "Tree Suite") RunSpecs(t, "Tree Suite")
} }

View File

@ -18,8 +18,7 @@ package version_test
import ( import (
"testing" "testing"
. "github.com/mudler/luet/cmd" . "github.com/mudler/luet/cmd/util"
config "github.com/mudler/luet/pkg/config"
. "github.com/onsi/ginkgo" . "github.com/onsi/ginkgo"
. "github.com/onsi/gomega" . "github.com/onsi/gomega"
@ -27,6 +26,6 @@ import (
func TestVersioner(t *testing.T) { func TestVersioner(t *testing.T) {
RegisterFailHandler(Fail) RegisterFailHandler(Fail)
LoadConfig(config.LuetCfg) LoadConfig()
RunSpecs(t, "Versioner Suite") RunSpecs(t, "Versioner Suite")
} }