From 2701ea58f6cfd29c1e96260bd793cc0d737cb7e3 Mon Sep 17 00:00:00 2001 From: Federico Di Pierro Date: Thu, 11 Apr 2024 10:52:11 +0200 Subject: [PATCH 1/5] new(cmd,pkg,docs,docgen,validate): switched from `slog` go library to use rich-text falcoctl log library. Signed-off-by: Federico Di Pierro --- cmd/completion.go | 5 +- cmd/config_options.go | 100 ++++++++++++-- cmd/docker.go | 34 +++-- cmd/images.go | 15 +- cmd/kubernetes.go | 59 ++++---- cmd/kubernetes_in_cluster.go | 62 +++++---- cmd/local.go | 37 +++-- cmd/root.go | 168 ++++++----------------- cmd/root_options.go | 83 +++++++---- docgen/docgen.go | 34 +++-- docs/driverkit.md | 5 +- docs/driverkit_docker.md | 4 +- docs/driverkit_images.md | 4 +- docs/driverkit_kubernetes-in-cluster.md | 4 +- docs/driverkit_kubernetes.md | 5 +- docs/driverkit_local.md | 36 +++++ go.mod | 27 +++- go.sum | 167 +++++++++++++++++++++- pkg/driverbuilder/builder/amazonlinux.go | 4 - pkg/driverbuilder/builder/build.go | 3 + pkg/driverbuilder/builder/builders.go | 29 ++-- pkg/driverbuilder/builder/image.go | 38 ++--- pkg/driverbuilder/docker.go | 78 +++++------ pkg/driverbuilder/kubernetes.go | 39 +++--- pkg/driverbuilder/local.go | 36 ++--- validate/isloglevel.go | 32 ----- validate/validate.go | 14 -- 27 files changed, 698 insertions(+), 424 deletions(-) create mode 100644 docs/driverkit_local.md delete mode 100644 validate/isloglevel.go diff --git a/cmd/completion.go b/cmd/completion.go index 4c4ecc88..b1199cad 100644 --- a/cmd/completion.go +++ b/cmd/completion.go @@ -17,6 +17,7 @@ package cmd import ( "bytes" "fmt" + "github.com/spf13/pflag" "os" "strings" "text/template" @@ -46,12 +47,12 @@ func validateArgs() cobra.PositionalArgs { if len(args) == 0 { return nil } - return cobra.ExactValidArgs(1)(c, args) + return cobra.MatchAll(cobra.ExactArgs(1), cobra.OnlyValidArgs)(c, args) } } // NewCompletionCmd ... -func NewCompletionCmd() *cobra.Command { +func NewCompletionCmd(_ *ConfigOptions, _ *RootOptions, _ *pflag.FlagSet) *cobra.Command { var long bytes.Buffer tmpl := template.Must(template.New("long").Parse(longUsageTemplate)) tmpl.Execute(&long, map[string]interface{}{ diff --git a/cmd/config_options.go b/cmd/config_options.go index 80176298..76affe18 100644 --- a/cmd/config_options.go +++ b/cmd/config_options.go @@ -15,51 +15,123 @@ limitations under the License. package cmd import ( + "errors" "fmt" - "log/slog" + "github.com/falcosecurity/falcoctl/pkg/options" + "github.com/falcosecurity/falcoctl/pkg/output" + "github.com/mitchellh/go-homedir" + "github.com/spf13/pflag" + "github.com/spf13/viper" + "io" "os" + "strings" "github.com/creasty/defaults" "github.com/falcosecurity/driverkit/validate" "github.com/go-playground/validator/v10" + "github.com/pterm/pterm" ) var validProcessors = []string{"docker", "kubernetes", "kubernetes-in-cluster", "local"} var aliasProcessors = []string{"docker", "k8s", "k8s-ic"} -var configOptions *ConfigOptions // ConfigOptions represent the persistent configuration flags of driverkit. type ConfigOptions struct { ConfigFile string - LogLevel string `validate:"loglevel" name:"log level" default:"INFO"` Timeout int `validate:"number,min=30" default:"120" name:"timeout"` ProxyURL string `validate:"omitempty,proxy" name:"proxy url"` DryRun bool - configErrors bool + // Printer used by all commands to output messages. + Printer *output.Printer + // Writer is used to write the output of the printer. + Writer io.Writer + logLevel *options.LogLevel +} + +func (co *ConfigOptions) initPrinter() { + logLevel := co.logLevel.ToPtermLogLevel() + co.Printer = output.NewPrinter(logLevel, pterm.LogFormatterColorful, co.Writer) } // NewConfigOptions creates an instance of ConfigOptions. -func NewConfigOptions() *ConfigOptions { - o := &ConfigOptions{} +func NewConfigOptions() (*ConfigOptions, error) { + o := &ConfigOptions{ + Writer: os.Stdout, + logLevel: options.NewLogLevel(), + } + o.initPrinter() if err := defaults.Set(o); err != nil { - slog.With("err", err.Error(), "options", "ConfigOptions").Error("error setting driverkit options defaults") - os.Exit(1) + // Return ConfigOptions anyway because we need the logger + return o, err } - return o + return o, nil } // Validate validates the ConfigOptions fields. -func (co *ConfigOptions) Validate() []error { +func (co *ConfigOptions) validate() []error { if err := validate.V.Struct(co); err != nil { - errors := err.(validator.ValidationErrors) - errArr := []error{} - for _, e := range errors { + var errs validator.ValidationErrors + errors.As(err, &errs) + var errArr []error + for _, e := range errs { // Translate each error one at a time errArr = append(errArr, fmt.Errorf(e.Translate(validate.T))) } - co.configErrors = true return errArr } return nil } + +// AddFlags registers the common flags. +func (co *ConfigOptions) AddFlags(flags *pflag.FlagSet) { + flags.StringVarP(&co.ConfigFile, "config", "c", co.ConfigFile, "config file path (default $HOME/.driverkit.yaml if exists)") + flags.VarP(co.logLevel, "loglevel", "l", "Set level for logs "+co.logLevel.Allowed()) + flags.IntVar(&co.Timeout, "timeout", co.Timeout, "timeout in seconds") + flags.StringVar(&co.ProxyURL, "proxy", co.ProxyURL, "the proxy to use to download data") + flags.BoolVar(&co.DryRun, "dryrun", co.DryRun, "do not actually perform the action") +} + +// Init reads in config file and ENV variables if set. +func (co *ConfigOptions) Init() bool { + configErr := false + if errs := co.validate(); errs != nil { + for _, err := range errs { + co.Printer.Logger.Error("error validating config options", + co.Printer.Logger.Args("err", err.Error())) + } + configErr = true + } + if co.ConfigFile != "" { + viper.SetConfigFile(co.ConfigFile) + } else { + // Find home directory. + home, err := homedir.Dir() + if err != nil { + co.Printer.Logger.Error("error getting the home directory", + co.Printer.Logger.Args("err", err.Error())) + // not setting configErr = true because we fallback to `$HOME/.driverkit.yaml` and try with it + } + + viper.AddConfigPath(home) + viper.SetConfigName(".driverkit") + } + + viper.AutomaticEnv() + viper.SetEnvPrefix("driverkit") + viper.SetEnvKeyReplacer(strings.NewReplacer("-", "_")) + + // If a config file is found, read it in. + if err := viper.ReadInConfig(); err == nil { + co.Printer.Logger.Info("using config file", + co.Printer.Logger.Args("file", viper.ConfigFileUsed())) + } else { + var configFileNotFoundError viper.ConfigFileNotFoundError + if errors.As(err, &configFileNotFoundError) { + // Config file not found, ignore ... + co.Printer.Logger.Debug("running without a configuration file") + } + } + co.initPrinter() + return configErr +} diff --git a/cmd/docker.go b/cmd/docker.go index c77ecfd6..ac737a13 100644 --- a/cmd/docker.go +++ b/cmd/docker.go @@ -15,32 +15,38 @@ limitations under the License. package cmd import ( - "log/slog" - "os" - + "bytes" "github.com/falcosecurity/driverkit/pkg/driverbuilder" "github.com/spf13/cobra" "github.com/spf13/pflag" - "github.com/spf13/viper" ) // NewDockerCmd creates the `driverkit docker` command. -func NewDockerCmd(rootOpts *RootOptions, rootFlags *pflag.FlagSet) *cobra.Command { +func NewDockerCmd(configOpts *ConfigOptions, rootOpts *RootOptions, rootFlags *pflag.FlagSet) *cobra.Command { dockerCmd := &cobra.Command{ Use: "docker", Short: "Build Falco kernel modules and eBPF probes against a docker daemon.", - Run: func(c *cobra.Command, args []string) { - slog.With("processor", c.Name()).Info("driver building, it will take a few seconds") - if !configOptions.DryRun { - b := rootOpts.ToBuild() + RunE: func(c *cobra.Command, args []string) error { + configOpts.Printer.Logger.Info("starting build", + configOpts.Printer.Logger.Args("processor", c.Name())) + if !configOpts.DryRun { + // Since we use a spinner, cache log data to a bytesbuffer; + // we will later print it once we stop the spinner. + var buf bytes.Buffer + b := rootOpts.ToBuild(configOpts.Printer.WithWriter(&buf)) + defer func() { + configOpts.Printer.DefaultText.Print(buf.String()) + }() if !b.HasOutputs() { - return - } - if err := driverbuilder.NewDockerBuildProcessor(viper.GetInt("timeout"), viper.GetString("proxy")).Start(b); err != nil { - slog.With("err", err.Error()).Error("exiting") - os.Exit(1) + return nil } + configOpts.Printer.Spinner, _ = configOpts.Printer.Spinner.Start("driver building, it will take a few seconds") + defer func() { + _ = configOpts.Printer.Spinner.Stop() + }() + return driverbuilder.NewDockerBuildProcessor(configOpts.Timeout, configOpts.ProxyURL).Start(b) } + return nil }, } // Add root flags diff --git a/cmd/images.go b/cmd/images.go index 010622b8..e8507fe0 100644 --- a/cmd/images.go +++ b/cmd/images.go @@ -15,7 +15,7 @@ limitations under the License. package cmd import ( - "log/slog" + "bytes" "os" "github.com/olekukonko/tablewriter" @@ -24,14 +24,21 @@ import ( ) // NewImagesCmd creates the `driverkit images` command. -func NewImagesCmd(rootOpts *RootOptions, rootFlags *pflag.FlagSet) *cobra.Command { +func NewImagesCmd(configOpts *ConfigOptions, rootOpts *RootOptions, rootFlags *pflag.FlagSet) *cobra.Command { imagesCmd := &cobra.Command{ Use: "images", Short: "List builder images", Run: func(c *cobra.Command, args []string) { - slog.With("processor", c.Name()).Info("listing images") - b := rootOpts.ToBuild() + configOpts.Printer.Logger.Info("starting loading images", + configOpts.Printer.Logger.Args("processor", c.Name())) + // Since we use a spinner, cache log data to a bytesbuffer; + // we will later print it once we stop the spinner. + var buf bytes.Buffer + b := rootOpts.ToBuild(configOpts.Printer.WithWriter(&buf)) + configOpts.Printer.Spinner, _ = configOpts.Printer.Spinner.Start("listing images, it will take a few seconds") b.LoadImages() + _ = configOpts.Printer.Spinner.Stop() + configOpts.Printer.DefaultText.Print(buf.String()) table := tablewriter.NewWriter(os.Stdout) table.SetHeader([]string{"Image", "Target", "Arch", "GCC"}) diff --git a/cmd/kubernetes.go b/cmd/kubernetes.go index 081fd20b..53d1f7d1 100644 --- a/cmd/kubernetes.go +++ b/cmd/kubernetes.go @@ -15,8 +15,8 @@ limitations under the License. package cmd import ( - "log/slog" - "os" + "bytes" + "github.com/falcosecurity/driverkit/pkg/driverbuilder/builder" "regexp" "strings" @@ -24,12 +24,11 @@ import ( "github.com/falcosecurity/driverkit/pkg/kubernetes/factory" "github.com/spf13/cobra" "github.com/spf13/pflag" - "github.com/spf13/viper" "k8s.io/cli-runtime/pkg/genericclioptions" ) // NewKubernetesCmd creates the `driverkit kubernetes` command. -func NewKubernetesCmd(rootOpts *RootOptions, rootFlags *pflag.FlagSet) *cobra.Command { +func NewKubernetesCmd(configOpts *ConfigOptions, rootOpts *RootOptions, rootFlags *pflag.FlagSet) *cobra.Command { kubernetesCmd := &cobra.Command{ Use: "kubernetes", Short: "Build Falco kernel modules and eBPF probes against a Kubernetes cluster.", @@ -58,34 +57,36 @@ func NewKubernetesCmd(rootOpts *RootOptions, rootFlags *pflag.FlagSet) *cobra.Co kubefactory := factory.NewFactory(configFlags) - kubernetesCmd.Run = func(cmd *cobra.Command, args []string) { - slog.With("processor", cmd.Name()).Info("driver building, it will take a few seconds") - if !configOptions.DryRun { - if err := kubernetesRun(cmd, args, kubefactory, rootOpts); err != nil { - slog.With("err", err.Error()).Error("exiting") - os.Exit(1) + kubernetesCmd.RunE = func(c *cobra.Command, args []string) error { + configOpts.Printer.Logger.Info("starting build", + configOpts.Printer.Logger.Args("processor", c.Name())) + if !configOpts.DryRun { + // Since we use a spinner, cache log data to a bytesbuffer; + // we will later print it once we stop the spinner. + var buf bytes.Buffer + b := rootOpts.ToBuild(configOpts.Printer.WithWriter(&buf)) + defer func() { + configOpts.Printer.DefaultText.Print(buf.String()) + }() + if !b.HasOutputs() { + return nil } + configOpts.Printer.Spinner, _ = configOpts.Printer.Spinner.Start("driver building, it will take a few seconds") + defer func() { + _ = configOpts.Printer.Spinner.Stop() + }() + return kubernetesRun(kubefactory, b, configOpts) } + return nil } return kubernetesCmd } -func kubernetesRun(cmd *cobra.Command, args []string, kubefactory factory.Factory, rootOpts *RootOptions) error { - f := cmd.Flags() - b := rootOpts.ToBuild() - if !b.HasOutputs() { - return nil - } - - namespaceStr, err := f.GetString("namespace") - if err != nil { - return err - } - if len(namespaceStr) == 0 { - namespaceStr = "default" - } - +func kubernetesRun(kubefactory factory.Factory, + b *builder.Build, + configOpts *ConfigOptions, +) error { kc, err := kubefactory.KubernetesClientSet() if err != nil { return err @@ -98,6 +99,12 @@ func kubernetesRun(cmd *cobra.Command, args []string, kubefactory factory.Factor return err } - buildProcessor := driverbuilder.NewKubernetesBuildProcessor(kc.CoreV1(), clientConfig, kubernetesOptions.RunAsUser, kubernetesOptions.Namespace, kubernetesOptions.ImagePullSecret, viper.GetInt("timeout"), viper.GetString("proxy")) + buildProcessor := driverbuilder.NewKubernetesBuildProcessor(kc.CoreV1(), + clientConfig, + kubernetesOptions.RunAsUser, + kubernetesOptions.Namespace, + kubernetesOptions.ImagePullSecret, + configOpts.Timeout, + configOpts.ProxyURL) return buildProcessor.Start(b) } diff --git a/cmd/kubernetes_in_cluster.go b/cmd/kubernetes_in_cluster.go index febdb0d7..d1d57310 100644 --- a/cmd/kubernetes_in_cluster.go +++ b/cmd/kubernetes_in_cluster.go @@ -15,20 +15,18 @@ limitations under the License. package cmd import ( - "log/slog" - "os" - + "bytes" "github.com/falcosecurity/driverkit/pkg/driverbuilder" + "github.com/falcosecurity/driverkit/pkg/driverbuilder/builder" "github.com/falcosecurity/driverkit/pkg/kubernetes/factory" "github.com/spf13/cobra" "github.com/spf13/pflag" - "github.com/spf13/viper" "k8s.io/client-go/kubernetes" "k8s.io/client-go/rest" ) // NewKubernetesInClusterCmd creates the `driverkit kubernetes` command. -func NewKubernetesInClusterCmd(rootOpts *RootOptions, rootFlags *pflag.FlagSet) *cobra.Command { +func NewKubernetesInClusterCmd(configOpts *ConfigOptions, rootOpts *RootOptions, rootFlags *pflag.FlagSet) *cobra.Command { kubernetesInClusterCmd := &cobra.Command{ Use: "kubernetes-in-cluster", Short: "Build Falco kernel modules and eBPF probes against a Kubernetes cluster inside a Kubernetes cluster.", @@ -42,32 +40,39 @@ func NewKubernetesInClusterCmd(rootOpts *RootOptions, rootFlags *pflag.FlagSet) // Add root flags kubernetesInClusterCmd.PersistentFlags().AddFlagSet(rootFlags) - kubernetesInClusterCmd.Run = func(cmd *cobra.Command, args []string) { - slog.With("processor", cmd.Name()).Info("driver building, it will take a few seconds") - if !configOptions.DryRun { - config, err := rest.InClusterConfig() - if err != nil { - slog.With("err", err.Error()).Error("exiting") - os.Exit(1) - } - if err = factory.SetKubernetesDefaults(config); err != nil { - slog.With("err", err.Error()).Error("exiting") - os.Exit(1) - } - if err = kubernetesInClusterRun(cmd, args, config, rootOpts); err != nil { - slog.With("err", err.Error()).Error("exiting") - os.Exit(1) + kubernetesInClusterCmd.RunE = func(c *cobra.Command, args []string) error { + configOpts.Printer.Logger.Info("starting build", + configOpts.Printer.Logger.Args("processor", c.Name())) + if !configOpts.DryRun { + // Since we use a spinner, cache log data to a bytesbuffer; + // we will later print it once we stop the spinner. + var buf bytes.Buffer + b := rootOpts.ToBuild(configOpts.Printer.WithWriter(&buf)) + defer func() { + configOpts.Printer.DefaultText.Print(buf.String()) + }() + if !b.HasOutputs() { + return nil } + configOpts.Printer.Spinner, _ = configOpts.Printer.Spinner.Start("driver building, it will take a few seconds") + defer func() { + _ = configOpts.Printer.Spinner.Stop() + }() + return kubernetesInClusterRun(b, configOpts) } + return nil } return kubernetesInClusterCmd } -func kubernetesInClusterRun(_ *cobra.Command, _ []string, kubeConfig *rest.Config, rootOpts *RootOptions) error { - b := rootOpts.ToBuild() - if !b.HasOutputs() { - return nil +func kubernetesInClusterRun(b *builder.Build, configOpts *ConfigOptions) error { + kubeConfig, err := rest.InClusterConfig() + if err != nil { + return err + } + if err = factory.SetKubernetesDefaults(kubeConfig); err != nil { + return err } kc, err := kubernetes.NewForConfig(kubeConfig) @@ -75,7 +80,12 @@ func kubernetesInClusterRun(_ *cobra.Command, _ []string, kubeConfig *rest.Confi return err } - buildProcessor := driverbuilder.NewKubernetesBuildProcessor(kc.CoreV1(), kubeConfig, kubernetesOptions.RunAsUser, kubernetesOptions.Namespace, kubernetesOptions.ImagePullSecret, viper.GetInt("timeout"), viper.GetString("proxy")) - + buildProcessor := driverbuilder.NewKubernetesBuildProcessor(kc.CoreV1(), + kubeConfig, + kubernetesOptions.RunAsUser, + kubernetesOptions.Namespace, + kubernetesOptions.ImagePullSecret, + configOpts.Timeout, + configOpts.ProxyURL) return buildProcessor.Start(b) } diff --git a/cmd/local.go b/cmd/local.go index edc4b835..1d48e215 100644 --- a/cmd/local.go +++ b/cmd/local.go @@ -1,12 +1,10 @@ package cmd import ( + "bytes" "github.com/falcosecurity/driverkit/pkg/driverbuilder" "github.com/spf13/cobra" "github.com/spf13/pflag" - "github.com/spf13/viper" - "log/slog" - "os" ) type localCmdOptions struct { @@ -17,27 +15,36 @@ type localCmdOptions struct { } // NewLocalCmd creates the `driverkit local` command. -func NewLocalCmd(rootOpts *RootOptions, rootFlags *pflag.FlagSet) *cobra.Command { +func NewLocalCmd(configOpts *ConfigOptions, rootOpts *RootOptions, rootFlags *pflag.FlagSet) *cobra.Command { opts := localCmdOptions{} localCmd := &cobra.Command{ Use: "local", Short: "Build Falco kernel modules and eBPF probes in local env with local kernel sources and gcc/clang.", - Run: func(c *cobra.Command, args []string) { - slog.With("processor", c.Name()).Info("driver building, it will take a few seconds") - if !configOptions.DryRun { - b := rootOpts.ToBuild() + RunE: func(c *cobra.Command, args []string) error { + configOpts.Printer.Logger.Info("starting build", + configOpts.Printer.Logger.Args("processor", c.Name())) + if !configOpts.DryRun { + // Since we use a spinner, cache log data to a bytesbuffer; + // we will later print it once we stop the spinner. + var buf bytes.Buffer + b := rootOpts.ToBuild(configOpts.Printer.WithWriter(&buf)) + defer func() { + configOpts.Printer.DefaultText.Print(buf.String()) + }() if !b.HasOutputs() { - return + return nil } - if err := driverbuilder.NewLocalBuildProcessor(viper.GetInt("timeout"), - opts.useDKMS, + configOpts.Printer.Spinner, _ = configOpts.Printer.Spinner.Start("driver building, it will take a few seconds") + defer func() { + _ = configOpts.Printer.Spinner.Stop() + }() + return driverbuilder.NewLocalBuildProcessor(opts.useDKMS, opts.downloadHeaders, opts.srcDir, - opts.envMap).Start(b); err != nil { - slog.With("err", err.Error()).Error("exiting") - os.Exit(1) - } + opts.envMap, + configOpts.Timeout).Start(b) } + return nil }, } // Add root flags, but not the ones unneeded diff --git a/cmd/root.go b/cmd/root.go index 077a2fa1..3e52d10d 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -16,30 +16,24 @@ package cmd import ( "fmt" - "io" - "log/slog" "os" - "runtime" "sort" "strings" - "github.com/falcosecurity/driverkit/pkg/kernelrelease" - "github.com/falcosecurity/driverkit/validate" - "github.com/falcosecurity/driverkit/pkg/driverbuilder/builder" + "github.com/falcosecurity/driverkit/pkg/kernelrelease" "github.com/falcosecurity/driverkit/pkg/version" "github.com/spf13/cobra" "github.com/spf13/pflag" - homedir "github.com/mitchellh/go-homedir" "github.com/spf13/viper" ) -func persistentValidateFunc(rootCommand *RootCmd, rootOpts *RootOptions) func(c *cobra.Command, args []string) error { +func persistentValidateFunc(rootCommand *RootCmd, configOpts *ConfigOptions, rootOpts *RootOptions) func(c *cobra.Command, args []string) error { return func(c *cobra.Command, args []string) error { - initConfig() + configErr := configOpts.Init() // Early exit if detect some error into config flags - if configOptions.configErrors { + if configErr { return fmt.Errorf("exiting for validation errors") } // Merge environment variables or config file values into the RootOptions instance @@ -61,13 +55,13 @@ func persistentValidateFunc(rootCommand *RootCmd, rootOpts *RootOptions) func(c // rather than replace, it appends. Since viper will already have the cli options set // if supplied, we only need this step if rootCommand doesn't already have them e.g. // not set on CLI so read from config. - if cli_urls, err := rootCommand.c.Flags().GetStringSlice(name); err == nil && len(cli_urls) != 0 { + if cliURLs, err := rootCommand.c.Flags().GetStringSlice(name); err == nil && len(cliURLs) != 0 { return } value := viper.GetStringSlice(name) if len(value) != 0 { strValue := strings.Join(value, ",") - rootCommand.c.Flags().Set(name, strValue) + _ = rootCommand.c.Flags().Set(name, strValue) } } else { value := viper.GetString(name) @@ -79,7 +73,7 @@ func persistentValidateFunc(rootCommand *RootCmd, rootOpts *RootOptions) func(c } // set the value, if any, otherwise let the default if value != "" { - rootCommand.c.Flags().Set(name, value) + _ = rootCommand.c.Flags().Set(name, value) } } } @@ -92,11 +86,12 @@ func persistentValidateFunc(rootCommand *RootCmd, rootOpts *RootOptions) func(c if c.Root() != c && c.Name() != "help" && c.Name() != "__complete" && c.Name() != "__completeNoDesc" && c.Name() != "completion" { if errs := rootOpts.Validate(); errs != nil { for _, err := range errs { - slog.With("err", err.Error()).Error("error validating build options") + configOpts.Printer.Logger.Error("error validating build options", + configOpts.Printer.Logger.Args("err", err.Error())) } return fmt.Errorf("exiting for validation errors") } - rootOpts.Log() + rootOpts.Log(configOpts.Printer) } return nil } @@ -108,9 +103,7 @@ type RootCmd struct { } // NewRootCmd instantiates the root command. -func NewRootCmd() *RootCmd { - configOptions = NewConfigOptions() - rootOpts := NewRootOptions() +func NewRootCmd(configOpts *ConfigOptions, rootOpts *RootOptions) *RootCmd { rootCmd := &cobra.Command{ Use: "driverkit", Short: "A command line tool to build Falco kernel modules and eBPF probes.", @@ -122,71 +115,46 @@ func NewRootCmd() *RootCmd { Version: version.String(), Run: func(c *cobra.Command, args []string) { if len(args) == 0 { - slog.With("processors", validProcessors).Info("specify a valid processor") + configOpts.Printer.Logger.Info("specify a valid processor", configOpts.Printer.Logger.Args("processors", validProcessors)) } // Fallback to help - c.Help() + _ = c.Help() }, } ret := &RootCmd{ c: rootCmd, } - rootCmd.PersistentPreRunE = persistentValidateFunc(ret, rootOpts) + rootCmd.PersistentPreRunE = persistentValidateFunc(ret, configOpts, rootOpts) flags := rootCmd.Flags() targets := builder.Targets() sort.Strings(targets) - flags.StringVarP(&configOptions.ConfigFile, "config", "c", configOptions.ConfigFile, "config file path (default $HOME/.driverkit.yaml if exists)") - flags.StringVarP(&configOptions.LogLevel, "loglevel", "l", configOptions.LogLevel, "log level") - flags.IntVar(&configOptions.Timeout, "timeout", configOptions.Timeout, "timeout in seconds") - flags.BoolVar(&configOptions.DryRun, "dryrun", configOptions.DryRun, "do not actually perform the action") - flags.StringVar(&configOptions.ProxyURL, "proxy", configOptions.ProxyURL, "the proxy to use to download data") - - flags.StringVar(&rootOpts.Output.Module, "output-module", rootOpts.Output.Module, "filepath where to save the resulting kernel module") - flags.StringVar(&rootOpts.Output.Probe, "output-probe", rootOpts.Output.Probe, "filepath where to save the resulting eBPF probe") - flags.StringVar(&rootOpts.Architecture, "architecture", runtime.GOARCH, "target architecture for the built driver, one of "+kernelrelease.SupportedArchs.String()) - flags.StringVar(&rootOpts.DriverVersion, "driverversion", rootOpts.DriverVersion, "driver version as a git commit hash or as a git tag") - flags.StringVar(&rootOpts.KernelVersion, "kernelversion", rootOpts.KernelVersion, "kernel version to build the module for, it's the numeric value after the hash when you execute 'uname -v'") - flags.StringVar(&rootOpts.KernelRelease, "kernelrelease", rootOpts.KernelRelease, "kernel release to build the module for, it can be found by executing 'uname -v'") - flags.StringVarP(&rootOpts.Target, "target", "t", rootOpts.Target, "the system to target the build for, one of ["+strings.Join(targets, ",")+"]") - flags.StringVar(&rootOpts.KernelConfigData, "kernelconfigdata", rootOpts.KernelConfigData, "base64 encoded kernel config data: in some systems it can be found under the /boot directory, in other it is gzip compressed under /proc") - flags.StringVar(&rootOpts.ModuleDeviceName, "moduledevicename", rootOpts.ModuleDeviceName, "kernel module device name (the default is falco, so the device will be under /dev/falco*)") - flags.StringVar(&rootOpts.ModuleDriverName, "moduledrivername", rootOpts.ModuleDriverName, "kernel module driver name, i.e. the name you see when you check installed modules via lsmod") - flags.StringVar(&rootOpts.BuilderImage, "builderimage", rootOpts.BuilderImage, "docker image to be used to build the kernel module and eBPF probe. If not provided, an automatically selected image will be used.") - flags.StringSliceVar(&rootOpts.BuilderRepos, "builderrepo", rootOpts.BuilderRepos, "list of docker repositories or yaml file (absolute path) containing builder images index with the format 'images: [ { target:, name:, arch: , tag: , gcc_versions: [ ] },...]', in descending priority order. Used to search for builder images. eg: --builderrepo myorg/driverkit-builder --builderrepo falcosecurity/driverkit-builder --builderrepo '/path/to/my/index.yaml'.") - flags.StringVar(&rootOpts.GCCVersion, "gccversion", rootOpts.GCCVersion, "enforce a specific gcc version for the build") - - flags.StringSliceVar(&rootOpts.KernelUrls, "kernelurls", nil, "list of kernel header urls (e.g. --kernelurls --kernelurls --kernelurls \",\")") - - flags.StringVar(&rootOpts.Repo.Org, "repo-org", rootOpts.Repo.Org, "repository github organization") - flags.StringVar(&rootOpts.Repo.Name, "repo-name", rootOpts.Repo.Name, "repository github name") - - flags.StringVar(&rootOpts.Registry.Name, "registry-name", rootOpts.Registry.Name, "registry name to which authenticate") - flags.StringVar(&rootOpts.Registry.Username, "registry-user", rootOpts.Registry.Username, "registry username") - flags.StringVar(&rootOpts.Registry.Password, "registry-password", rootOpts.Registry.Password, "registry password") - flags.BoolVar(&rootOpts.Registry.PlainHTTP, "registry-plain-http", rootOpts.Registry.PlainHTTP, "allows interacting with remote registry via plain http requests") + configOpts.AddFlags(flags) + rootOpts.AddFlags(flags, targets) - viper.BindPFlags(flags) + if err := viper.BindPFlags(flags); err != nil { + panic(err) + } // Flag annotations and custom completions - rootCmd.MarkFlagFilename("config", viper.SupportedExts...) - rootCmd.RegisterFlagCompletionFunc("target", func(c *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + _ = rootCmd.MarkFlagFilename("config", viper.SupportedExts...) + _ = rootCmd.RegisterFlagCompletionFunc("target", func(c *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { return targets, cobra.ShellCompDirectiveDefault }) - rootCmd.RegisterFlagCompletionFunc("architecture", func(c *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + _ = rootCmd.RegisterFlagCompletionFunc("architecture", func(c *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { return kernelrelease.SupportedArchs.Strings(), cobra.ShellCompDirectiveDefault }) // Subcommands - rootCmd.AddCommand(NewKubernetesCmd(rootOpts, flags)) - rootCmd.AddCommand(NewKubernetesInClusterCmd(rootOpts, flags)) - rootCmd.AddCommand(NewDockerCmd(rootOpts, flags)) - rootCmd.AddCommand(NewLocalCmd(rootOpts, flags)) - rootCmd.AddCommand(NewImagesCmd(rootOpts, flags)) - rootCmd.AddCommand(NewCompletionCmd()) + rootCmd.AddCommand(NewKubernetesCmd(configOpts, rootOpts, flags)) + rootCmd.AddCommand(NewKubernetesInClusterCmd(configOpts, rootOpts, flags)) + rootCmd.AddCommand(NewDockerCmd(configOpts, rootOpts, flags)) + rootCmd.AddCommand(NewLocalCmd(configOpts, rootOpts, flags)) + rootCmd.AddCommand(NewImagesCmd(configOpts, rootOpts, flags)) + rootCmd.AddCommand(NewCompletionCmd(configOpts, rootOpts, flags)) ret.StripSensitive() @@ -215,29 +183,6 @@ func (r *RootCmd) Command() *cobra.Command { return r.c } -func createDefaultLogger(w io.Writer) { - h := slog.NewTextHandler(w, &slog.HandlerOptions{ - Level: validate.ProgramLevel, - ReplaceAttr: func(groups []string, a slog.Attr) slog.Attr { - if a.Key == slog.TimeKey { - return slog.Attr{} - } - return a - }}) - slog.SetDefault(slog.New(h)) -} - -// SetOutput sets the main command output writer. -func (r *RootCmd) SetOutput(w io.Writer) { - r.c.SetOut(w) - r.c.SetErr(w) - createDefaultLogger(w) -} - -func init() { - createDefaultLogger(os.Stdout) -} - // SetArgs proxies the arguments to the underlying cobra.Command. func (r *RootCmd) SetArgs(args []string) { r.c.SetArgs(args) @@ -250,50 +195,23 @@ func (r *RootCmd) Execute() error { // Start creates the root command and runs it. func Start() { - root := NewRootCmd() - if err := root.Execute(); err != nil { - slog.With("err", err.Error()).Error("error executing driverkit") - os.Exit(1) - } -} - -// initConfig reads in config file and ENV variables if set. -func initConfig() { - if errs := configOptions.Validate(); errs != nil { - for _, err := range errs { - slog.With("err", err.Error()).Error("error validating config options") + configOpts, err := NewConfigOptions() + if err != nil { + // configOpts will never be nil here + if configOpts != nil { + configOpts.Printer.Logger.Fatal("error setting driverkit config options defaults", + configOpts.Printer.Logger.Args("err", err.Error())) + } else { + os.Exit(1) } - // configOptions.configErrors should be true here } - if configOptions.ConfigFile != "" { - viper.SetConfigFile(configOptions.ConfigFile) - } else { - // Find home directory. - home, err := homedir.Dir() - if err != nil { - slog.With("err", err.Error()).Debug("error getting the home directory") - // not setting configOptions.configErrors = true because we fallback to `$HOME/.driverkit.yaml` and try with it - } - - viper.AddConfigPath(home) - viper.SetConfigName(".driverkit") + rootOpts, err := NewRootOptions() + if err != nil { + configOpts.Printer.Logger.Fatal("error setting driverkit root options defaults", + configOpts.Printer.Logger.Args("err", err.Error())) } - - viper.AutomaticEnv() - viper.SetEnvPrefix("driverkit") - viper.SetEnvKeyReplacer(strings.NewReplacer("-", "_")) - - // If a config file is found, read it in. - if err := viper.ReadInConfig(); err == nil { - slog.With("file", viper.ConfigFileUsed()).Info("using config file") - } else { - if _, ok := err.(viper.ConfigFileNotFoundError); ok { - // Config file not found, ignore ... - slog.Debug("running without a configuration file") - } else { - // Config file was found but another error was produced - slog.With("file", viper.ConfigFileUsed(), "err", err.Error()).Debug("error running with config file") - configOptions.configErrors = true - } + root := NewRootCmd(configOpts, rootOpts) + if err = root.Execute(); err != nil { + configOpts.Printer.Logger.Fatal("error executing driverkit", configOpts.Printer.Logger.Args("err", err.Error())) } } diff --git a/cmd/root_options.go b/cmd/root_options.go index b9814faa..efb064a7 100644 --- a/cmd/root_options.go +++ b/cmd/root_options.go @@ -15,9 +15,13 @@ limitations under the License. package cmd import ( + "errors" "fmt" - "log/slog" + "github.com/falcosecurity/falcoctl/pkg/output" + "github.com/spf13/pflag" "os" + "runtime" + "strings" "github.com/creasty/defaults" "github.com/falcosecurity/driverkit/pkg/driverbuilder/builder" @@ -68,21 +72,21 @@ func init() { } // NewRootOptions ... -func NewRootOptions() *RootOptions { +func NewRootOptions() (*RootOptions, error) { rootOpts := &RootOptions{} if err := defaults.Set(rootOpts); err != nil { - slog.With("err", err.Error(), "options", "RootOptions").Error("error setting driverkit options defaults") - os.Exit(1) + return nil, err } - return rootOpts + return rootOpts, nil } // Validate validates the RootOptions fields. func (ro *RootOptions) Validate() []error { if err := validate.V.Struct(ro); err != nil { - errors := err.(validator.ValidationErrors) + var errs validator.ValidationErrors + errors.As(err, &errs) errArr := []error{} - for _, e := range errors { + for _, e := range errs { // Translate each error one at a time errArr = append(errArr, fmt.Errorf(e.Translate(validate.T))) } @@ -99,25 +103,52 @@ func (ro *RootOptions) Validate() []error { return nil } +func (ro *RootOptions) AddFlags(flags *pflag.FlagSet, targets []string) { + flags.StringVar(&ro.Output.Module, "output-module", ro.Output.Module, "filepath where to save the resulting kernel module") + flags.StringVar(&ro.Output.Probe, "output-probe", ro.Output.Probe, "filepath where to save the resulting eBPF probe") + flags.StringVar(&ro.Architecture, "architecture", runtime.GOARCH, "target architecture for the built driver, one of "+kernelrelease.SupportedArchs.String()) + flags.StringVar(&ro.DriverVersion, "driverversion", ro.DriverVersion, "driver version as a git commit hash or as a git tag") + flags.StringVar(&ro.KernelVersion, "kernelversion", ro.KernelVersion, "kernel version to build the module for, it's the numeric value after the hash when you execute 'uname -v'") + flags.StringVar(&ro.KernelRelease, "kernelrelease", ro.KernelRelease, "kernel release to build the module for, it can be found by executing 'uname -v'") + flags.StringVarP(&ro.Target, "target", "t", ro.Target, "the system to target the build for, one of ["+strings.Join(targets, ",")+"]") + flags.StringVar(&ro.KernelConfigData, "kernelconfigdata", ro.KernelConfigData, "base64 encoded kernel config data: in some systems it can be found under the /boot directory, in other it is gzip compressed under /proc") + flags.StringVar(&ro.ModuleDeviceName, "moduledevicename", ro.ModuleDeviceName, "kernel module device name (the default is falco, so the device will be under /dev/falco*)") + flags.StringVar(&ro.ModuleDriverName, "moduledrivername", ro.ModuleDriverName, "kernel module driver name, i.e. the name you see when you check installed modules via lsmod") + flags.StringVar(&ro.BuilderImage, "builderimage", ro.BuilderImage, "docker image to be used to build the kernel module and eBPF probe. If not provided, an automatically selected image will be used.") + flags.StringSliceVar(&ro.BuilderRepos, "builderrepo", ro.BuilderRepos, "list of docker repositories or yaml file (absolute path) containing builder images index with the format 'images: [ { target:, name:, arch: , tag: , gcc_versions: [ ] },...]', in descending priority order. Used to search for builder images. eg: --builderrepo myorg/driverkit-builder --builderrepo falcosecurity/driverkit-builder --builderrepo '/path/to/my/index.yaml'.") + flags.StringVar(&ro.GCCVersion, "gccversion", ro.GCCVersion, "enforce a specific gcc version for the build") + + flags.StringSliceVar(&ro.KernelUrls, "kernelurls", nil, "list of kernel header urls (e.g. --kernelurls --kernelurls --kernelurls \",\")") + + flags.StringVar(&ro.Repo.Org, "repo-org", ro.Repo.Org, "repository github organization") + flags.StringVar(&ro.Repo.Name, "repo-name", ro.Repo.Name, "repository github name") + + flags.StringVar(&ro.Registry.Name, "registry-name", ro.Registry.Name, "registry name to which authenticate") + flags.StringVar(&ro.Registry.Username, "registry-user", ro.Registry.Username, "registry username") + flags.StringVar(&ro.Registry.Password, "registry-password", ro.Registry.Password, "registry password") + flags.BoolVar(&ro.Registry.PlainHTTP, "registry-plain-http", ro.Registry.PlainHTTP, "allows interacting with remote registry via plain http requests") +} + // Log emits a log line containing the receiving RootOptions for debugging purposes. // // Call it only after validation. -func (ro *RootOptions) Log() { - slog.Debug("running with options", - "output-module", ro.Output.Module, - "output-probe", ro.Output.Probe, - "driverversion", ro.DriverVersion, - "kernelrelease", ro.KernelRelease, - "kernelversion", ro.KernelVersion, - "target", ro.Target, - "arch", ro.Architecture, - "kernelurls", ro.KernelUrls, - "repo-org", ro.Repo.Org, - "repo-name", ro.Repo.Name, - ) +func (ro *RootOptions) Log(printer *output.Printer) { + printer.Logger.Debug("running with options", + printer.Logger.Args( + "output-module", ro.Output.Module, + "output-probe", ro.Output.Probe, + "driverversion", ro.DriverVersion, + "kernelrelease", ro.KernelRelease, + "kernelversion", ro.KernelVersion, + "target", ro.Target, + "arch", ro.Architecture, + "kernelurls", ro.KernelUrls, + "repo-org", ro.Repo.Org, + "repo-name", ro.Repo.Name, + )) } -func (ro *RootOptions) ToBuild() *builder.Build { +func (ro *RootOptions) ToBuild(printer *output.Printer) *builder.Build { kernelConfigData := ro.KernelConfigData if len(kernelConfigData) == 0 { kernelConfigData = "bm8tZGF0YQ==" // no-data @@ -145,6 +176,7 @@ func (ro *RootOptions) ToBuild() *builder.Build { RegistryUser: ro.Registry.Username, RegistryPassword: ro.Registry.Password, RegistryPlainHTTP: ro.Registry.PlainHTTP, + Printer: printer, } // loop over BuilderRepos to build the list ImagesListers based on the value of the builderRepo: @@ -160,7 +192,8 @@ func (ro *RootOptions) ToBuild() *builder.Build { imageLister, err = builder.NewRepoImagesLister(builderRepo, build) } if err != nil { - slog.With("err", err.Error()).Warn("Skipping repo", "repo", builderRepo) + printer.Logger.Warn("skipping repo", + printer.Logger.Args("repo", builderRepo, "err", err.Error())) } else { build.ImagesListers = append(build.ImagesListers, imageLister) } @@ -170,11 +203,13 @@ func (ro *RootOptions) ToBuild() *builder.Build { kr := build.KernelReleaseFromBuildConfig() if len(build.ModuleFilePath) > 0 && !kr.SupportsModule() { build.ModuleFilePath = "" - slog.Warn("Skipping build attempt of module for unsupported kernel release", "kernelrelease", kr.String()) + printer.Logger.Warn("skipping build attempt of module for unsupported kernel release", + printer.Logger.Args("kernelrelease", kr.String())) } if len(build.ProbeFilePath) > 0 && !kr.SupportsProbe() { build.ProbeFilePath = "" - slog.Warn("Skipping build attempt of probe for unsupported kernel release", "kernelrelease", kr.String()) + printer.Logger.Warn("skipping build attempt of probe for unsupported kernel release", + printer.Logger.Args("kernelrelease", kr.String())) } return build } diff --git a/docgen/docgen.go b/docgen/docgen.go index 9b504fb2..89405836 100644 --- a/docgen/docgen.go +++ b/docgen/docgen.go @@ -18,8 +18,6 @@ import ( "bytes" "flag" "fmt" - "io/ioutil" - "log/slog" "os" "path" "strings" @@ -61,7 +59,22 @@ func main() { flag.Parse() // Get root command - driverkit := cmd.NewRootCmd() + configOpts, err := cmd.NewConfigOptions() + if err != nil { + // configOpts will never be nil here + if configOpts != nil { + configOpts.Printer.Logger.Fatal("error setting driverkit config options defaults", + configOpts.Printer.Logger.Args("err", err.Error())) + } else { + os.Exit(1) + } + } + rootOpts, err := cmd.NewRootOptions() + if err != nil { + configOpts.Printer.Logger.Fatal("error setting driverkit root options defaults", + configOpts.Printer.Logger.Args("err", err.Error())) + } + driverkit := cmd.NewRootCmd(configOpts, rootOpts) root := driverkit.Command() num := len(root.Commands()) + 1 @@ -84,23 +97,20 @@ func main() { } // Generate markdown docs - err := doc.GenMarkdownTreeCustom(root, outputDir, prepender(num), linker) + err = doc.GenMarkdownTreeCustom(root, outputDir, prepender(num), linker) if err != nil { - slog.With("err", err.Error()).Error("markdown generation") - os.Exit(1) + configOpts.Printer.Logger.Fatal("markdown generation", configOpts.Printer.Logger.Args("err", err.Error())) } if targetWebsite { err = os.Rename(path.Join(outputDir, "driverkit.md"), path.Join(outputDir, "_index.md")) if err != nil { - slog.With("err", err.Error()).Error("renaming main docs page") - os.Exit(1) + configOpts.Printer.Logger.Fatal("renaming main docs page", configOpts.Printer.Logger.Args("err", err.Error())) } } if err = stripSensitive(); err != nil { - slog.With("err", err.Error()).Error("error replacing sensitive data") - os.Exit(1) + configOpts.Printer.Logger.Fatal("error replacing sensitive data", configOpts.Printer.Logger.Args("err", err.Error())) } } @@ -117,7 +127,7 @@ func stripSensitive() error { for _, file := range files { filePath := path.Join(outputDir, file.Name()) - file, err := ioutil.ReadFile(filePath) + file, err := os.ReadFile(filePath) if err != nil { return err } @@ -127,7 +137,7 @@ func stripSensitive() error { target := []byte(os.Getenv(s)) file = bytes.ReplaceAll(file, target, append(envMark, []byte(s)...)) } - if err = ioutil.WriteFile(filePath, file, 0666); err != nil { + if err = os.WriteFile(filePath, file, 0666); err != nil { return err } } diff --git a/docs/driverkit.md b/docs/driverkit.md index 09ba03d8..5f8d02d1 100644 --- a/docs/driverkit.md +++ b/docs/driverkit.md @@ -21,7 +21,7 @@ driverkit --kernelrelease string kernel release to build the module for, it can be found by executing 'uname -v' --kernelurls strings list of kernel header urls (e.g. --kernelurls --kernelurls --kernelurls ",") --kernelversion string kernel version to build the module for, it's the numeric value after the hash when you execute 'uname -v' (default "1") - -l, --loglevel string log level (default "INFO") + -l, --loglevel string Set level for logs (info, warn, debug, trace) (default "info") --moduledevicename string kernel module device name (the default is falco, so the device will be under /dev/falco*) (default "falco") --moduledrivername string kernel module driver name, i.e. the name you see when you check installed modules via lsmod (default "falco") --output-module string filepath where to save the resulting kernel module @@ -33,7 +33,7 @@ driverkit --registry-user string registry username --repo-name string repository github name (default "libs") --repo-org string repository github organization (default "falcosecurity") - -t, --target string the system to target the build for, one of [alinux,almalinux,amazonlinux,amazonlinux2,amazonlinux2022,amazonlinux2023,arch,bottlerocket,centos,debian,fedora,flatcar,minikube,ol,opensuse,photon,redhat,rocky,talos,ubuntu,vanilla] + -t, --target string the system to target the build for, one of [alinux,almalinux,amazonlinux,amazonlinux2,amazonlinux2022,amazonlinux2023,arch,bottlerocket,centos,debian,fedora,flatcar,minikube,ol,opensuse,photon,redhat,rocky,sles,talos,ubuntu,vanilla] --timeout int timeout in seconds (default 120) ``` @@ -44,4 +44,5 @@ driverkit * [driverkit images](driverkit_images.md) - List builder images * [driverkit kubernetes](driverkit_kubernetes.md) - Build Falco kernel modules and eBPF probes against a Kubernetes cluster. * [driverkit kubernetes-in-cluster](driverkit_kubernetes-in-cluster.md) - Build Falco kernel modules and eBPF probes against a Kubernetes cluster inside a Kubernetes cluster. +* [driverkit local](driverkit_local.md) - Build Falco kernel modules and eBPF probes in local env with local kernel sources and gcc/clang. diff --git a/docs/driverkit_docker.md b/docs/driverkit_docker.md index 880a0f32..44265719 100644 --- a/docs/driverkit_docker.md +++ b/docs/driverkit_docker.md @@ -21,7 +21,7 @@ driverkit docker [flags] --kernelrelease string kernel release to build the module for, it can be found by executing 'uname -v' --kernelurls strings list of kernel header urls (e.g. --kernelurls --kernelurls --kernelurls ",") --kernelversion string kernel version to build the module for, it's the numeric value after the hash when you execute 'uname -v' (default "1") - -l, --loglevel string log level (default "INFO") + -l, --loglevel string Set level for logs (info, warn, debug, trace) (default "info") --moduledevicename string kernel module device name (the default is falco, so the device will be under /dev/falco*) (default "falco") --moduledrivername string kernel module driver name, i.e. the name you see when you check installed modules via lsmod (default "falco") --output-module string filepath where to save the resulting kernel module @@ -33,7 +33,7 @@ driverkit docker [flags] --registry-user string registry username --repo-name string repository github name (default "libs") --repo-org string repository github organization (default "falcosecurity") - -t, --target string the system to target the build for, one of [alinux,almalinux,amazonlinux,amazonlinux2,amazonlinux2022,amazonlinux2023,arch,bottlerocket,centos,debian,fedora,flatcar,minikube,ol,opensuse,photon,redhat,rocky,talos,ubuntu,vanilla] + -t, --target string the system to target the build for, one of [alinux,almalinux,amazonlinux,amazonlinux2,amazonlinux2022,amazonlinux2023,arch,bottlerocket,centos,debian,fedora,flatcar,minikube,ol,opensuse,photon,redhat,rocky,sles,talos,ubuntu,vanilla] --timeout int timeout in seconds (default 120) ``` diff --git a/docs/driverkit_images.md b/docs/driverkit_images.md index 03a26895..dd33663d 100644 --- a/docs/driverkit_images.md +++ b/docs/driverkit_images.md @@ -21,7 +21,7 @@ driverkit images [flags] --kernelrelease string kernel release to build the module for, it can be found by executing 'uname -v' --kernelurls strings list of kernel header urls (e.g. --kernelurls --kernelurls --kernelurls ",") --kernelversion string kernel version to build the module for, it's the numeric value after the hash when you execute 'uname -v' (default "1") - -l, --loglevel string log level (default "INFO") + -l, --loglevel string Set level for logs (info, warn, debug, trace) (default "info") --moduledevicename string kernel module device name (the default is falco, so the device will be under /dev/falco*) (default "falco") --moduledrivername string kernel module driver name, i.e. the name you see when you check installed modules via lsmod (default "falco") --output-module string filepath where to save the resulting kernel module @@ -33,7 +33,7 @@ driverkit images [flags] --registry-user string registry username --repo-name string repository github name (default "libs") --repo-org string repository github organization (default "falcosecurity") - -t, --target string the system to target the build for, one of [alinux,almalinux,amazonlinux,amazonlinux2,amazonlinux2022,amazonlinux2023,arch,bottlerocket,centos,debian,fedora,flatcar,minikube,ol,opensuse,photon,redhat,rocky,talos,ubuntu,vanilla] + -t, --target string the system to target the build for, one of [alinux,almalinux,amazonlinux,amazonlinux2,amazonlinux2022,amazonlinux2023,arch,bottlerocket,centos,debian,fedora,flatcar,minikube,ol,opensuse,photon,redhat,rocky,sles,talos,ubuntu,vanilla] --timeout int timeout in seconds (default 120) ``` diff --git a/docs/driverkit_kubernetes-in-cluster.md b/docs/driverkit_kubernetes-in-cluster.md index 41d1f69c..b756aec8 100644 --- a/docs/driverkit_kubernetes-in-cluster.md +++ b/docs/driverkit_kubernetes-in-cluster.md @@ -22,7 +22,7 @@ driverkit kubernetes-in-cluster [flags] --kernelrelease string kernel release to build the module for, it can be found by executing 'uname -v' --kernelurls strings list of kernel header urls (e.g. --kernelurls --kernelurls --kernelurls ",") --kernelversion string kernel version to build the module for, it's the numeric value after the hash when you execute 'uname -v' (default "1") - -l, --loglevel string log level (default "INFO") + -l, --loglevel string Set level for logs (info, warn, debug, trace) (default "info") --moduledevicename string kernel module device name (the default is falco, so the device will be under /dev/falco*) (default "falco") --moduledrivername string kernel module driver name, i.e. the name you see when you check installed modules via lsmod (default "falco") -n, --namespace string If present, the namespace scope for the pods and its config (default "default") @@ -36,7 +36,7 @@ driverkit kubernetes-in-cluster [flags] --repo-name string repository github name (default "libs") --repo-org string repository github organization (default "falcosecurity") --run-as-user int Pods runner user - -t, --target string the system to target the build for, one of [alinux,almalinux,amazonlinux,amazonlinux2,amazonlinux2022,amazonlinux2023,arch,bottlerocket,centos,debian,fedora,flatcar,minikube,ol,opensuse,photon,redhat,rocky,talos,ubuntu,vanilla] + -t, --target string the system to target the build for, one of [alinux,almalinux,amazonlinux,amazonlinux2,amazonlinux2022,amazonlinux2023,arch,bottlerocket,centos,debian,fedora,flatcar,minikube,ol,opensuse,photon,redhat,rocky,sles,talos,ubuntu,vanilla] --timeout int timeout in seconds (default 120) ``` diff --git a/docs/driverkit_kubernetes.md b/docs/driverkit_kubernetes.md index b322c193..edb294db 100644 --- a/docs/driverkit_kubernetes.md +++ b/docs/driverkit_kubernetes.md @@ -22,6 +22,7 @@ driverkit kubernetes [flags] --cluster string the name of the kubeconfig cluster to use -c, --config string config file path (default $HOME/.driverkit.yaml if exists) --context string the name of the kubeconfig context to use + --disable-compression if true, opt-out of response compression for all requests to the server --driverversion string driver version as a git commit hash or as a git tag (default "master") --dryrun do not actually perform the action --gccversion string enforce a specific gcc version for the build @@ -33,7 +34,7 @@ driverkit kubernetes [flags] --kernelurls strings list of kernel header urls (e.g. --kernelurls --kernelurls --kernelurls ",") --kernelversion string kernel version to build the module for, it's the numeric value after the hash when you execute 'uname -v' (default "1") --kubeconfig string path to the kubeconfig file to use for CLI requests - -l, --loglevel string log level (default "info") + -l, --loglevel string Set level for logs (info, warn, debug, trace) (default "info") --moduledevicename string kernel module device name (the default is falco, so the device will be under /dev/falco*) (default "falco") --moduledrivername string kernel module driver name, i.e. the name you see when you check installed modules via lsmod (default "falco") -n, --namespace string If present, the namespace scope for the pods and its config (default "default") @@ -49,7 +50,7 @@ driverkit kubernetes [flags] --request-timeout string the length of time to wait before giving up on a single server request, non-zero values should contain a corresponding time unit (e.g, 1s, 2m, 3h), a value of zero means don't timeout requests (default "0") --run-as-user int Pods runner user -s, --server string the address and port of the Kubernetes API server - -t, --target string the system to target the build for, one of [alinux,almalinux,amazonlinux,amazonlinux2,amazonlinux2022,amazonlinux2023,arch,bottlerocket,centos,debian,fedora,flatcar,minikube,ol,opensuse,photon,redhat,rocky,talos,ubuntu,vanilla] + -t, --target string the system to target the build for, one of [alinux,almalinux,amazonlinux,amazonlinux2,amazonlinux2022,amazonlinux2023,arch,bottlerocket,centos,debian,fedora,flatcar,minikube,ol,opensuse,photon,redhat,rocky,sles,talos,ubuntu,vanilla] --timeout int timeout in seconds (default 120) --tls-server-name string server name to use for server certificate validation, if it is not provided, the hostname used to contact the server is used --token string bearer token for authentication to the API server diff --git a/docs/driverkit_local.md b/docs/driverkit_local.md new file mode 100644 index 00000000..56caf140 --- /dev/null +++ b/docs/driverkit_local.md @@ -0,0 +1,36 @@ +## driverkit local + +Build Falco kernel modules and eBPF probes in local env with local kernel sources and gcc/clang. + +``` +driverkit local [flags] +``` + +### Options + +``` + -c, --config string config file path (default $HOME/.driverkit.yaml if exists) + --dkms Enforce usage of DKMS to build the kernel module. + --download-headers Try to automatically download kernel headers. + --driverversion string driver version as a git commit hash or as a git tag (default "master") + --dryrun do not actually perform the action + --env stringToString Env variables to be enforced during the driver build. (default []) + -h, --help help for local + --kernelrelease string kernel release to build the module for, it can be found by executing 'uname -v' + --kernelversion string kernel version to build the module for, it's the numeric value after the hash when you execute 'uname -v' (default "1") + -l, --loglevel string Set level for logs (info, warn, debug, trace) (default "info") + --moduledevicename string kernel module device name (the default is falco, so the device will be under /dev/falco*) (default "falco") + --moduledrivername string kernel module driver name, i.e. the name you see when you check installed modules via lsmod (default "falco") + --output-module string filepath where to save the resulting kernel module + --output-probe string filepath where to save the resulting eBPF probe + --repo-name string repository github name (default "libs") + --repo-org string repository github organization (default "falcosecurity") + --src-dir string Enforce usage of local source dir to build drivers. + -t, --target string the system to target the build for, one of [alinux,almalinux,amazonlinux,amazonlinux2,amazonlinux2022,amazonlinux2023,arch,bottlerocket,centos,debian,fedora,flatcar,minikube,ol,opensuse,photon,redhat,rocky,sles,talos,ubuntu,vanilla] + --timeout int timeout in seconds (default 120) +``` + +### SEE ALSO + +* [driverkit](driverkit.md) - A command line tool to build Falco kernel modules and eBPF probes. + diff --git a/go.mod b/go.mod index 59aa3ace..cfba2dd8 100644 --- a/go.mod +++ b/go.mod @@ -30,19 +30,31 @@ require ( require ( github.com/falcosecurity/falcoctl v0.7.3 github.com/olekukonko/tablewriter v0.0.5 + github.com/pterm/pterm v0.12.67 gopkg.in/yaml.v3 v3.0.1 oras.land/oras-go/v2 v2.5.0 ) require ( + atomicgo.dev/cursor v0.2.0 // indirect + atomicgo.dev/keyboard v0.2.9 // indirect + atomicgo.dev/schedule v0.1.0 // indirect + cloud.google.com/go v0.110.10 // indirect + cloud.google.com/go/compute v1.23.3 // indirect + cloud.google.com/go/compute/metadata v0.2.3 // indirect + cloud.google.com/go/iam v1.1.5 // indirect + cloud.google.com/go/storage v1.35.1 // indirect github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect github.com/MakeNowJust/heredoc v1.0.0 // indirect github.com/Microsoft/go-winio v0.6.1 // indirect github.com/chai2010/gettext-go v1.0.2 // indirect + github.com/containerd/console v1.0.3 // indirect github.com/containerd/log v0.1.0 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.3 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/distribution/reference v0.6.0 // indirect + github.com/docker/cli v24.0.7+incompatible // indirect + github.com/docker/docker-credential-helpers v0.8.0 // indirect github.com/docker/go-connections v0.5.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/dustin/go-humanize v1.0.1 // indirect @@ -61,13 +73,18 @@ require ( github.com/go-openapi/jsonreference v0.21.0 // indirect github.com/go-openapi/swag v0.23.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.4 // indirect github.com/google/btree v1.1.2 // indirect github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49 // indirect github.com/google/go-cmp v0.6.0 // indirect github.com/google/gofuzz v1.2.0 // indirect + github.com/google/s2a-go v0.1.7 // indirect github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect github.com/google/uuid v1.6.0 // indirect + github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect + github.com/googleapis/gax-go/v2 v2.12.0 // indirect + github.com/gookit/color v1.5.4 // indirect github.com/gorilla/websocket v1.5.1 // indirect github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect @@ -79,6 +96,7 @@ require ( github.com/klauspost/compress v1.17.7 // indirect github.com/leodido/go-urn v1.4.0 // indirect github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect + github.com/lithammer/fuzzysearch v1.1.8 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-isatty v0.0.20 // indirect @@ -107,12 +125,13 @@ require ( github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect - github.com/sergi/go-diff v1.2.0 // indirect github.com/sourcegraph/conc v0.3.0 // indirect github.com/spf13/afero v1.11.0 // indirect github.com/spf13/cast v1.6.0 // indirect github.com/subosito/gotenv v1.6.0 // indirect github.com/xlab/treeprint v1.2.0 // indirect + github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect + go.opencensus.io v0.24.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect go.opentelemetry.io/otel v1.24.0 // indirect go.opentelemetry.io/otel/metric v1.24.0 // indirect @@ -130,7 +149,13 @@ require ( golang.org/x/text v0.14.0 // indirect golang.org/x/time v0.5.0 // indirect golang.org/x/tools v0.19.0 // indirect + golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect + google.golang.org/api v0.153.0 // indirect google.golang.org/appengine v1.6.8 // indirect + google.golang.org/genproto v0.0.0-20231106174013-bbf56f31fb17 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20231106174013-bbf56f31fb17 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f // indirect + google.golang.org/grpc v1.59.0 // indirect google.golang.org/protobuf v1.33.0 // indirect gopkg.in/evanphx/json-patch.v5 v5.9.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect diff --git a/go.sum b/go.sum index 247bb6f0..65c42edc 100644 --- a/go.sum +++ b/go.sum @@ -1,9 +1,38 @@ +atomicgo.dev/assert v0.0.2 h1:FiKeMiZSgRrZsPo9qn/7vmr7mCsh5SZyXY4YGYiYwrg= +atomicgo.dev/assert v0.0.2/go.mod h1:ut4NcI3QDdJtlmAxQULOmA13Gz6e2DWbSAS8RUOmNYQ= +atomicgo.dev/cursor v0.2.0 h1:H6XN5alUJ52FZZUkI7AlJbUc1aW38GWZalpYRPpoPOw= +atomicgo.dev/cursor v0.2.0/go.mod h1:Lr4ZJB3U7DfPPOkbH7/6TOtJ4vFGHlgj1nc+n900IpU= +atomicgo.dev/keyboard v0.2.9 h1:tOsIid3nlPLZ3lwgG8KZMp/SFmr7P0ssEN5JUsm78K8= +atomicgo.dev/keyboard v0.2.9/go.mod h1:BC4w9g00XkxH/f1HXhW2sXmJFOCWbKn9xrOunSFtExQ= +atomicgo.dev/schedule v0.1.0 h1:nTthAbhZS5YZmgYbb2+DH8uQIZcTlIrd4eYr3UQxEjs= +atomicgo.dev/schedule v0.1.0/go.mod h1:xeUa3oAkiuHYh8bKiQBRojqAMq3PXXbJujjb0hw8pEU= +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.110.10 h1:LXy9GEO+timppncPIAZoOj3l58LIU9k+kn48AN7IO3Y= +cloud.google.com/go v0.110.10/go.mod h1:v1OoFqYxiBkUrruItNM3eT4lLByNjxmJSV/xDKJNnic= +cloud.google.com/go/compute v1.23.3 h1:6sVlXXBmbd7jNX0Ipq0trII3e4n1/MsADLK6a+aiVlk= +cloud.google.com/go/compute v1.23.3/go.mod h1:VCgBUoMnIVIR0CscqQiPJLAG25E3ZRZMzcFZeQ+h8CI= +cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= +cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= +cloud.google.com/go/iam v1.1.5 h1:1jTsCu4bcsNsE4iiqNT5SHwrDRCfRmIaaaVFhRveTJI= +cloud.google.com/go/iam v1.1.5/go.mod h1:rB6P/Ic3mykPbFio+vo7403drjlgvoWfYpJhMXEbzv8= +cloud.google.com/go/storage v1.35.1 h1:B59ahL//eDfx2IIKFBeT5Atm9wnNmj3+8xG/W4WB//w= +cloud.google.com/go/storage v1.35.1/go.mod h1:M6M/3V/D3KpzMTJyPOR/HU6n2Si5QdaXYEsng2xgOs8= github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 h1:bvDV9vkmnHYOMsOr4WLk+Vo07yKIzd94sVoIqshQ4bU= github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0= github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ= github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE= +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.8/go.mod h1:nwIcjmr0Zz+Rcwfh3/4UhBp7ePKVhuBExvZqnKYWlII= +github.com/MarvinJWendt/testza v0.2.10/go.mod h1:pd+VWsoGUiFtq+hRKSU1Bktnn+DMCSrDrXDpX2bG66k= +github.com/MarvinJWendt/testza v0.2.12/go.mod h1:JOIegYyV7rX+7VZ9r77L/eH6CfJHHzXjB69adAhzZkI= +github.com/MarvinJWendt/testza v0.3.0/go.mod h1:eFcL4I0idjtIx8P9C6KkAuLgATNKpX4/2oUqKc6bF2c= +github.com/MarvinJWendt/testza v0.4.2/go.mod h1:mSdhXiKH8sg/gQehJ63bINcCKp7RtYewEjXsvsVUPbE= +github.com/MarvinJWendt/testza v0.5.2 h1:53KDo64C1z/h/d/stCYCPY69bt/OSwjq5KpFNwi+zB4= +github.com/MarvinJWendt/testza v0.5.2/go.mod h1:xu53QFE5sCdjtMCKk8YMQ2MnymimEctc4n3EjyIYvEY= github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= github.com/Microsoft/hcsshim v0.11.4 h1:68vKo2VN8DE9AdN4tnkWnmdhqdbpUFM8OF3Airm7fz8= @@ -12,12 +41,18 @@ github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d h1:licZJFw2RwpH github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d/go.mod h1:asat636LX7Bqt5lYEZ27JNDcqxfjdBQuJ/MM4CN/Lzo= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= +github.com/atomicgo/cursor v0.0.1/go.mod h1:cBON2QmmrysudxNBFthvMtN32r3jxVRIvzkUiF/RuIk= github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ= github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/chai2010/gettext-go v1.0.2 h1:1Lwwip6Q2QGsAdl/ZKPCwTe9fe0CjlUbqj5bFNSjIRk= github.com/chai2010/gettext-go v1.0.2/go.mod h1:y+wnP2cHYaVj19NZhYKAwEMH2CI1gNHeQQ+5AjwawxA= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/containerd/console v1.0.3 h1:lIr7SlA5PxZyMV30bDW0MGbiOPXwc63yRuCP0ARubLw= +github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U= github.com/containerd/containerd v1.7.14 h1:H/XLzbnGuenZEGK+v0RkwTdv2u1QFAruMe5N0GNPJwA= github.com/containerd/containerd v1.7.14/go.mod h1:YMC9Qt5yzNqXx/fO4j/5yYVIHXSRrlB3H7sxkUTvspg= github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= @@ -34,8 +69,12 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1 github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v26.0.2+incompatible h1:yGVmKUFGgcxA6PXWAokO0sQL22BrQ67cgVjko8tGdXE= -github.com/docker/docker v26.0.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/cli v24.0.7+incompatible h1:wa/nIwYFW7BVTGa7SWPVyyXU9lgORqUb1xfI36MSkFg= +github.com/docker/cli v24.0.7+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/docker v26.0.0+incompatible h1:Ng2qi+gdKADUa/VM+6b6YaY2nlZhk/lVJiKR/2bMudU= +github.com/docker/docker v26.0.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker-credential-helpers v0.8.0 h1:YQFtbBQb4VrpoPxhFuzEBPQ9E16qz5SpHLS+uswaCp8= +github.com/docker/docker-credential-helpers v0.8.0/go.mod h1:UGFXcuoQ5TxPiB54nHOZ32AWRqQdECoh/Mg0AlEYb40= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= @@ -44,6 +83,10 @@ github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkp github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/emicklei/go-restful/v3 v3.12.0 h1:y2DdzBAURM29NFF94q6RaY4vjIH1rtwDapwQtU84iWk= github.com/emicklei/go-restful/v3 v3.12.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/evanphx/json-patch v5.9.0+incompatible h1:fBXyNpNMuTTDdquAq/uisOr2lShz4oaXpDTX2bLe7ls= github.com/evanphx/json-patch v5.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f h1:Wl78ApPPB2Wvf/TIe2xdyJxTlb6obmF18d8QdkxNDu4= @@ -87,6 +130,20 @@ github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEe github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= @@ -95,6 +152,12 @@ github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU= github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49 h1:0VpGH+cDhbDtdcweoyCVsF3fhN8kejK6rFe/2FFX2nU= github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49/go.mod h1:BkkQ4L1KS1xMt2aWSPStnn55ChGC0DPOn2FQYj+f25M= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= @@ -102,12 +165,25 @@ github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/martian/v3 v3.3.2 h1:IqNFLAmvJOgVlpdEBiQbDc2EwKW77amAycfTuWKdfvw= +github.com/google/martian/v3 v3.3.2/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= github.com/google/pprof v0.0.0-20231023181126-ff6d637d2a7b h1:RMpPgZTSApbPf7xaVel+QkoGPRLFLrwFO89uDUHEGf0= github.com/google/pprof v0.0.0-20231023181126-ff6d637d2a7b/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik= +github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o= +github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfFxPRy3Bf7vr3h0cechB90XaQs= +github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= +github.com/googleapis/gax-go/v2 v2.12.0 h1:A+gCJKdRfqXkr+BIRGtZLibNXf0m1f9E4HG56etFpas= +github.com/googleapis/gax-go/v2 v2.12.0/go.mod h1:y+aIqrI5eb1YGMVJfuV3185Ts/D7qKpsEkdD5+I6QGU= +github.com/gookit/color v1.4.2/go.mod h1:fqRyamkC1W8uxl+lxCQxOT09l/vYfZ+QeiX3rKQHCoQ= +github.com/gookit/color v1.5.0/go.mod h1:43aQb+Zerm/BWh2GnrgOQm7ffz7tvQXEKV6BFMl7wAo= +github.com/gookit/color v1.5.4 h1:FZmqs7XOyGgCAxmWyPslpiok1k05wmY3SJTytgvYFs0= +github.com/gookit/color v1.5.4/go.mod h1:pZJOeOS8DM43rXbp4AZo1n9zCU2qjpcRko0b6/QJi9w= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= @@ -131,6 +207,11 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg= github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= +github.com/klauspost/cpuid/v2 v2.0.10/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c= +github.com/klauspost/cpuid/v2 v2.0.12/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c= +github.com/klauspost/cpuid/v2 v2.2.3 h1:sxCkb+qR91z4vsqw4vGGZlDgPz3G7gjaLyK3V8y70BU= +github.com/klauspost/cpuid/v2 v2.2.3/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= @@ -142,6 +223,8 @@ github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de h1:9TO3cAIGXtEhnIaL+V+BEER86oLrvS+kWobKpbJuye0= github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9B/r2mtpb6U+EI2rYA5OAXxsYw6wTamcNW+zcE= +github.com/lithammer/fuzzysearch v1.1.8 h1:/HIuJnjHuXS8bKaiTMeeDlW2/AyIWk2brx1V8LFgLN4= +github.com/lithammer/fuzzysearch v1.1.8/go.mod h1:IdqeyBClc3FFqSzYq/MXESsS4S0FsZ5ajtkr5xPLts4= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= @@ -149,6 +232,7 @@ github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJ github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU= @@ -205,6 +289,16 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +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.31/go.mod h1:32ZAWZVXD7ZfG0s8qqHXePte42kdz8ECtRyEejaWgXU= +github.com/pterm/pterm v0.12.33/go.mod h1:x+h2uL+n7CP/rel9+bImHD5lF3nM9vJj80k9ybiiTTE= +github.com/pterm/pterm v0.12.36/go.mod h1:NjiL09hFhT/vWjQHSj1athJpx6H8cjpHXNAK5bUw8T8= +github.com/pterm/pterm v0.12.40/go.mod h1:ffwPLwlbXxP+rxT0GsgDTzS3y3rmpAO1NMjUkGTYf8s= +github.com/pterm/pterm v0.12.67 h1:5iB7ajIQROYfxYD7+sFJ4+KJhFJ+xn7QOVBm4s6RUF0= +github.com/pterm/pterm v0.12.67/go.mod h1:nFuT9ZVkkCi8o4L1dtWuYPwDQxggLh4C263qG5nTLpQ= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= @@ -245,6 +339,7 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= @@ -252,9 +347,14 @@ github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8 github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= github.com/xlab/treeprint v1.2.0 h1:HzHnuAF1plUN2zGlAFHbSQP2qJ0ZAD3XF5XD7OesXRQ= github.com/xlab/treeprint v1.2.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0= +github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778/go.mod h1:2MuV+tbUrU1zIOPMxZ5EncGwgmMJsa+9ucAQZXxsObs= +github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no= +github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= +go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 h1:jq9TW8u3so/bN+JPT166wjOI6/vQPF6Xe7nMNIltagk= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0/go.mod h1:p8pYQP+m5XfbZm9fxtSKAbM6oIllS7s2AfxrChvc7iw= go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= @@ -283,75 +383,135 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8 h1:aAcj0Da7eBAtrTp03QXWvm88pSyOt+UgdZw2BFZ+lEw= golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8/go.mod h1:CQ1k9gNrJ50XIzaKCRR2hssIjF07kZFEiieALBM/ARQ= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.16.0 h1:QX4fJ0Rr5cPQCF7O9lh9Se4pmwfwskqZfq5moyldzic= golang.org/x/mod v0.16.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +<<<<<<< HEAD golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= +======= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc= +golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +>>>>>>> 9723857 (new(cmd,pkg,docs,docgen,validate): switched from `slog` go library to use rich-text falcoctl log library.) golang.org/x/oauth2 v0.18.0 h1:09qnuIAgzdx1XplqJvW6CQqMCtGZykZWcXzPMPUusvI= golang.org/x/oauth2 v0.18.0/go.mod h1:Wf7knwG0MPoWIMMBgFlEaSUDaKskp0dCfrlJRJXbBi8= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211013075003-97ac67df715c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 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/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8= golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.19.0 h1:tfGCXNR1OsFG+sVdLAitlpjAvD/I6dHDKnYrpEZUHkw= golang.org/x/tools v0.19.0/go.mod h1:qoJWxmGSIBmAeriMx19ogtrEPrGtDbPK634QFIcLAhc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 h1:+cNy6SZtPcJQH3LJVLOSmiC7MMxXNOb3PU/VUEz+EhU= +golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90= +google.golang.org/api v0.153.0 h1:N1AwGhielyKFaUqH07/ZSIQR3uNPcV7NVw0vj+j4iR4= +google.golang.org/api v0.153.0/go.mod h1:3qNJX5eOmhiWYc67jRA/3GsDw97UFb5ivv7Y2PrriAY= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto v0.0.0-20231106174013-bbf56f31fb17 h1:wpZ8pe2x1Q3f2KyT5f8oP/fa9rHAKgFPr/HZdNuS+PQ= +google.golang.org/genproto v0.0.0-20231106174013-bbf56f31fb17/go.mod h1:J7XzRzVy1+IPwWHZUzoD0IccYZIrXILAQpc+Qy9CMhY= google.golang.org/genproto/googleapis/api v0.0.0-20231106174013-bbf56f31fb17 h1:JpwMPBpFN3uKhdaekDpiNlImDdkUAyiJ6ez/uxGaUSo= google.golang.org/genproto/googleapis/api v0.0.0-20231106174013-bbf56f31fb17/go.mod h1:0xJLfVdJqpAPl8tDg1ujOCGzx6LFLttXT5NhllGOXY4= google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f h1:ultW7fxlIvee4HYrtnaRPon9HpEgFk5zYpmfMgtKB5I= google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f/go.mod h1:L9KNLi232K1/xB6f7AlSX692koaRnKaWSR0stBki0Yc= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk= google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= @@ -372,12 +532,15 @@ gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= gotest.tools/v3 v3.4.0 h1:ZazjZUfuVeZGLAmlKKuyv3IKP5orXcwtOwDQH6YVr6o= gotest.tools/v3 v3.4.0/go.mod h1:CtbdzLSsqVhDgMtKsx03ird5YTGB3ar27v0u/yKBW5g= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= k8s.io/api v0.29.3 h1:2ORfZ7+bGC3YJqGpV0KSDDEVf8hdGQ6A03/50vj8pmw= k8s.io/api v0.29.3/go.mod h1:y2yg2NTyHUUkIoTC+phinTnEa3KFM6RZ3szxt014a80= k8s.io/apimachinery v0.29.3 h1:2tbx+5L7RNvqJjn7RIuIKu9XTsIZ9Z5wX2G22XAa5EU= diff --git a/pkg/driverbuilder/builder/amazonlinux.go b/pkg/driverbuilder/builder/amazonlinux.go index 44ce3c17..16b76934 100644 --- a/pkg/driverbuilder/builder/amazonlinux.go +++ b/pkg/driverbuilder/builder/amazonlinux.go @@ -25,7 +25,6 @@ import ( "io" "io/ioutil" "log" - "log/slog" "net/http" "os" "strings" @@ -212,7 +211,6 @@ func buildMirror(a amazonBuilder, r string, kv kernelrelease.KernelRelease) (str } mirror := fmt.Sprintf("%s/%s", baseURL, "mirror.list") - slog.With("url", mirror, "version", r).Debug("looking for repo...") return mirror, nil } @@ -261,7 +259,6 @@ func fetchAmazonLinuxPackagesURLs(a amazonBuilder, kv kernelrelease.KernelReleas } // Download the repo database repoRes, err := http.Get(repoDatabaseURL) - slog.With("url", repoDatabaseURL).Debug("downloading...") if err != nil { return nil, err } @@ -292,7 +289,6 @@ func fetchAmazonLinuxPackagesURLs(a amazonBuilder, kv kernelrelease.KernelReleas return nil, err } defer db.Close() - slog.With("db", dbFile.Name()).Debug("connecting to database...") // Query the database rel := strings.TrimPrefix(strings.TrimSuffix(kv.FullExtraversion, fmt.Sprintf(".%s", kv.Architecture.ToNonDeb())), "-") q := fmt.Sprintf("SELECT location_href FROM packages WHERE name LIKE 'kernel-devel%%' AND version='%s' AND release='%s'", kv.Fullversion, rel) diff --git a/pkg/driverbuilder/builder/build.go b/pkg/driverbuilder/builder/build.go index bc5f1da9..6d0e8558 100644 --- a/pkg/driverbuilder/builder/build.go +++ b/pkg/driverbuilder/builder/build.go @@ -17,6 +17,7 @@ package builder import ( "context" "fmt" + "github.com/falcosecurity/falcoctl/pkg/output" "strings" "github.com/falcosecurity/driverkit/pkg/kernelrelease" @@ -49,6 +50,8 @@ type Build struct { RegistryUser string RegistryPassword string RegistryPlainHTTP bool + + *output.Printer } func (b *Build) KernelReleaseFromBuildConfig() kernelrelease.KernelRelease { diff --git a/pkg/driverbuilder/builder/builders.go b/pkg/driverbuilder/builder/builders.go index 8667ad39..18269882 100644 --- a/pkg/driverbuilder/builder/builders.go +++ b/pkg/driverbuilder/builder/builders.go @@ -19,10 +19,9 @@ import ( _ "embed" "errors" "fmt" - "log/slog" + "github.com/falcosecurity/falcoctl/pkg/output" "net/http" "net/url" - "os" "path" "strings" "text/template" @@ -132,7 +131,11 @@ func LibsDownloadScript(c Config) (string, error) { } // KernelDownloadScript returns the script that will download and extract kernel headers -func KernelDownloadScript(b Builder, kernelurls []string, kr kernelrelease.KernelRelease) (string, error) { +func KernelDownloadScript(b Builder, + kernelurls []string, + kr kernelrelease.KernelRelease, + printer *output.Printer, +) (string, error) { t := template.New("download-kernel") parsed, err := t.Parse(b.TemplateKernelUrlsScript()) if err != nil { @@ -167,6 +170,9 @@ func KernelDownloadScript(b Builder, kernelurls []string, kr kernelrelease.Kerne return "", fmt.Errorf("not enough headers packages found; expected %d, found %d", minimumURLs, len(urls)) } + printer.Logger.Debug("kernel headers found", + printer.Logger.Args("urls", urls)) + td := b.KernelTemplateData(kr, urls) if tdErr, ok := td.(error); ok { return "", tdErr @@ -297,8 +303,10 @@ func (b *Build) setGCCVersion(builder Builder, kr kernelrelease.KernelRelease) { proposedGCCs := make([]semver.Version, 0) for _, img := range b.Images { proposedGCCs = append(proposedGCCs, img.GCCVersion) - slog.With("image", img.Name, "targetGCC", targetGCC.String()). - Debug("proposedGCC", "version", img.GCCVersion.String()) + b.Logger.Debug("proposed GCC", + b.Logger.Args("image", img.Name, + "targetGCC", targetGCC.String(), + "proposedGCC", img.GCCVersion.String())) } // Now, sort versions and fetch @@ -313,8 +321,8 @@ func (b *Build) setGCCVersion(builder Builder, kr kernelrelease.KernelRelease) { } b.GCCVersion = lastGCC.String() } - slog.With("targetGCC", targetGCC.String()). - Debug("foundGCC", "version", b.GCCVersion) + b.Logger.Debug("found GCC", + b.Logger.Args("targetGCC", targetGCC.String(), "version", b.GCCVersion)) } type BuilderImageNetworkMode interface { @@ -389,13 +397,11 @@ func (c Config) toTemplateData(b Builder, kr kernelrelease.KernelRelease) common func resolveURLReference(u string) string { uu, err := url.Parse(u) if err != nil { - slog.Error(err.Error()) - os.Exit(1) + panic(err) } base, err := url.Parse(uu.Host) if err != nil { - slog.Error(err.Error()) - os.Exit(1) + panic(err) } return base.ResolveReference(uu).String() } @@ -415,7 +421,6 @@ func GetResolvingURLs(urls []string) ([]string, error) { } if res.StatusCode == http.StatusOK { results = append(results, u) - slog.With("url", u).Debug("kernel header url found") } } if len(results) == 0 { diff --git a/pkg/driverbuilder/builder/image.go b/pkg/driverbuilder/builder/image.go index 97f9d8e4..affc70f8 100644 --- a/pkg/driverbuilder/builder/image.go +++ b/pkg/driverbuilder/builder/image.go @@ -17,7 +17,7 @@ package builder import ( "context" "fmt" - "log/slog" + "github.com/falcosecurity/falcoctl/pkg/output" "os" "regexp" "strings" @@ -47,7 +47,7 @@ type Image struct { } type ImagesLister interface { - LoadImages() []Image + LoadImages(printer *output.Printer) []Image } type FileImagesLister struct { @@ -98,7 +98,7 @@ func NewFileImagesLister(filePath string, build *Build) (*FileImagesLister, erro }, nil } -func (f *FileImagesLister) LoadImages() []Image { +func (f *FileImagesLister) LoadImages(printer *output.Printer) []Image { var ( res []Image imageList YAMLImagesList @@ -107,37 +107,43 @@ func (f *FileImagesLister) LoadImages() []Image { // loop over lines in file to print them fileData, err := os.ReadFile(f.FilePath) if err != nil { - slog.With("err", err.Error(), "FilePath", f.FilePath).Warn("Error opening builder repo file") + printer.Logger.Warn("error opening builder repo file", + printer.Logger.Args("err", err.Error(), "filepath", f.FilePath)) return res } err = yaml.Unmarshal(fileData, &imageList) if err != nil { - slog.With("err", err.Error(), "FilePath", f.FilePath).Warn("Error unmarshalling builder repo file") + printer.Logger.Warn("error unmarshalling builder repo file", + printer.Logger.Args("err", err.Error(), "filepath", f.FilePath)) return res } for _, image := range imageList.Images { - logger := slog.With("FilePath", f.FilePath, "image", image) // Values checks if image.Arch != f.Arch { - logger.Debug("Skipping wrong-arch image") + printer.Logger.Debug("skipping wrong-arch image", + printer.Logger.Args("filepath", f.FilePath, "image", image)) continue } if image.Tag != f.Tag { - logger.Debug("Skipping wrong-tag image") + printer.Logger.Debug("skipping wrong-tag image", + printer.Logger.Args("filepath", f.FilePath, "image", image)) continue } if image.Target != "any" && image.Target != f.Target { - logger.Debug("Skipping wrong-target image") + printer.Logger.Debug("skipping wrong-target image", + printer.Logger.Args("filepath", f.FilePath, "image", image)) continue } if image.Name == "" { - logger.Debug("Skipping empty name image") + printer.Logger.Debug("skipping empty name image", + printer.Logger.Args("filepath", f.FilePath, "image", image)) continue } if len(image.GCCVersions) == 0 { - logger.Debug("Expected at least 1 gcc version") + printer.Logger.Debug("expected at least 1 gcc version", + printer.Logger.Args("filepath", f.FilePath, "image", image)) continue } @@ -178,10 +184,11 @@ func NewRepoImagesLister(repo string, build *Build) (*RepoImagesLister, error) { return &RepoImagesLister{repoOCI}, nil } -func (repo *RepoImagesLister) LoadImages() []Image { +func (repo *RepoImagesLister) LoadImages(printer *output.Printer) []Image { tags, err := repo.Tags(context.Background()) if err != nil { - slog.With("Repo", repo.Reference, "err", err.Error()).Warn("Skipping repo") + printer.Logger.Warn("skipping repo", + printer.Logger.Args("repo", repo.Reference, "err", err.Error())) return nil } @@ -229,7 +236,7 @@ func (repo *RepoImagesLister) LoadImages() []Image { func (b *Build) LoadImages() { for _, imagesLister := range b.ImagesListers { - for _, image := range imagesLister.LoadImages() { + for _, image := range imagesLister.LoadImages(b.Printer) { // User forced a gcc version? Only load images matching the requested gcc version. if b.GCCVersion != "" && b.GCCVersion != image.GCCVersion.String() { continue @@ -241,8 +248,7 @@ func (b *Build) LoadImages() { } } if len(b.Images) == 0 { - slog.Error("Could not load any builder image. Leaving.") - os.Exit(1) + b.Printer.Logger.Fatal("Could not load any builder image. Leaving.") } } diff --git a/pkg/driverbuilder/docker.go b/pkg/driverbuilder/docker.go index d3dec409..ec782cab 100644 --- a/pkg/driverbuilder/docker.go +++ b/pkg/driverbuilder/docker.go @@ -22,11 +22,10 @@ import ( "encoding/base64" "encoding/binary" "fmt" + "github.com/docker/docker/api/types/image" + "github.com/falcosecurity/falcoctl/pkg/output" "io" - "io/ioutil" "log" - "log/slog" - "os" "runtime" "strconv" "strings" @@ -49,6 +48,7 @@ type DockerBuildProcessor struct { clean bool timeout int proxy string + *output.Printer } // NewDockerBuildProcessor ... @@ -63,7 +63,7 @@ func (bp *DockerBuildProcessor) String() string { return DockerBuildProcessorName } -func mustCheckArchUseQemu(ctx context.Context, b *builder.Build, cli *client.Client) { +func (bp *DockerBuildProcessor) mustCheckArchUseQemu(ctx context.Context, b *builder.Build, cli *client.Client) { var err error if b.Architecture == runtime.GOARCH { // Nothing to do @@ -71,18 +71,19 @@ func mustCheckArchUseQemu(ctx context.Context, b *builder.Build, cli *client.Cli } if runtime.GOARCH != kernelrelease.ArchitectureAmd64 { - log.Fatal("qemu-user-static image is only available for x86_64 hosts: https://github.com/multiarch/qemu-user-static#supported-host-architectures") + bp.Logger.Fatal("qemu-user-static image is only available for x86_64 hosts: https://github.com/multiarch/qemu-user-static#supported-host-architectures") } - slog.Debug("using qemu for cross build") + bp.Logger.Debug("using qemu for cross build") if _, _, err = cli.ImageInspectWithRaw(ctx, "multiarch/qemu-user-static"); client.IsErrNotFound(err) { - slog.With("image", "multiarch/qemu-user-static").Debug("pulling qemu static image") + bp.Logger.Debug("pulling qemu static image", + bp.Logger.Args("image", "multiarch/qemu-user-static")) pullRes, err := cli.ImagePull(ctx, "multiarch/qemu-user-static", types.ImagePullOptions{}) if err != nil { log.Fatal(err) } defer pullRes.Close() - _, err = io.Copy(ioutil.Discard, pullRes) + _, err = io.Copy(io.Discard, pullRes) if err != nil { log.Fatal(err) } @@ -98,8 +99,8 @@ func mustCheckArchUseQemu(ctx context.Context, b *builder.Build, cli *client.Cli Privileged: true, }, nil, nil, "") if err != nil { - slog.Error(err.Error()) - os.Exit(1) + bp.Logger.Fatal("failed to create qemu container", + bp.Logger.Args("err", err.Error())) } if err = cli.ContainerStart(ctx, qemuImage.ID, container.StartOptions{}); err != nil { @@ -117,14 +118,15 @@ func mustCheckArchUseQemu(ctx context.Context, b *builder.Build, cli *client.Cli err = cli.ContainerStop(ctx, qemuImage.ID, container.StopOptions{}) if err != nil && !client.IsErrNotFound(err) { - slog.Error(err.Error()) - os.Exit(1) + bp.Logger.Fatal("failed to stop qemu container", + bp.Logger.Args("err", err.Error())) } } // Start the docker processor func (bp *DockerBuildProcessor) Start(b *builder.Build) error { - slog.Debug("doing a new docker build") + bp.Printer = b.Printer + cli, err := client.NewClientWithOpts(client.FromEnv) if err != nil { return err @@ -145,7 +147,7 @@ func (bp *DockerBuildProcessor) Start(b *builder.Build) error { return err } - kernelDownloadScript, err := builder.KernelDownloadScript(v, c.KernelUrls, kr) + kernelDownloadScript, err := builder.KernelDownloadScript(v, c.KernelUrls, kr, b.Printer) if err != nil { return err } @@ -167,30 +169,27 @@ func (bp *DockerBuildProcessor) Start(b *builder.Build) error { ctx := context.Background() ctx = signals.WithStandardSignals(ctx) - mustCheckArchUseQemu(ctx, b, cli) + bp.mustCheckArchUseQemu(ctx, b, cli) var inspect types.ImageInspect if inspect, _, err = cli.ImageInspectWithRaw(ctx, builderImage); client.IsErrNotFound(err) || inspect.Architecture != b.Architecture { - slog. - With("image", builderImage, "arch", b.Architecture). - Debug("pulling builder image") + bp.Logger.Debug("pulling builder image", + bp.Logger.Args("image", builderImage, "arch", b.Architecture)) - pullRes, err := cli.ImagePull(ctx, builderImage, types.ImagePullOptions{Platform: b.Architecture}) + pullRes, err := cli.ImagePull(ctx, builderImage, image.PullOptions{Platform: b.Architecture}) if err != nil { return err } defer pullRes.Close() - _, err = io.Copy(ioutil.Discard, pullRes) + _, err = io.Copy(io.Discard, pullRes) if err != nil { return err } } - slog. - With("image", builderImage). - Debug("starting container") + bp.Logger.Debug("starting container", bp.Logger.Args("image", builderImage)) containerCfg := &container.Config{ Tty: true, @@ -312,23 +311,23 @@ chmod +x /driverkit/driverkit.sh isMultiplexed = val == "application/vnd.docker.multiplexed-stream" } if isMultiplexed { - multiplexedForwardLogs(hr.Reader) + bp.multiplexedForwardLogs(hr.Reader) } else { - forwardLogs(hr.Reader) + bp.forwardLogs(hr.Reader) } if len(b.ModuleFilePath) > 0 { if err := copyFromContainer(ctx, cli, cdata.ID, c.ToDriverFullPath(), b.ModuleFilePath); err != nil { return err } - slog.With("path", b.ModuleFilePath).Info("kernel module available") + bp.Logger.Info("kernel module available", bp.Logger.Args("path", b.ModuleFilePath)) } if len(b.ProbeFilePath) > 0 { if err := copyFromContainer(ctx, cli, cdata.ID, c.ToProbeFullPath(), b.ProbeFilePath); err != nil { return err } - slog.With("path", b.ProbeFilePath).Info("eBPF probe available") + bp.Logger.Info("eBPF probe available", bp.Logger.Args("path", b.ProbeFilePath)) } return nil @@ -353,10 +352,11 @@ func copyFromContainer(ctx context.Context, cli *client.Client, ID, from, to str func (bp *DockerBuildProcessor) cleanup(cli *client.Client, ID string) { if !bp.clean { bp.clean = true - slog.Debug("context canceled") + bp.Logger.Debug("context canceled") duration := 1 if err := cli.ContainerStop(context.Background(), ID, container.StopOptions{Timeout: &duration}); err != nil && !client.IsErrNotFound(err) { - slog.With("err", err.Error(), "container_id", ID).Error("error stopping container") + bp.Logger.Error("error stopping container", + bp.Logger.Args("err", err.Error())) } } } @@ -385,21 +385,21 @@ func tarWriterFiles(buf io.Writer, files []dockerCopyFile) error { return nil } -func forwardLogs(logPipe io.Reader) { +func (bp *DockerBuildProcessor) forwardLogs(logPipe io.Reader) { lineReader := bufio.NewReader(logPipe) for { line, err := lineReader.ReadBytes('\n') if len(line) > 0 { - slog.Debug(string(line)) + bp.Logger.Debug(string(line)) } if err == io.EOF { break } if err != nil { - slog.With("err", err.Error()).Error("log pipe error") + bp.Logger.Error("log pipe error", bp.Logger.Args("err", err.Error())) } } - slog.Debug("log pipe close") + bp.Logger.Debug("log pipe close") } // When docker container attach is called on a non-tty terminal, @@ -408,7 +408,7 @@ func forwardLogs(logPipe io.Reader) { // > The format of the multiplexed stream is as follows: // > [8]byte{STREAM_TYPE, 0, 0, 0, SIZE1, SIZE2, SIZE3, SIZE4}[]byte{OUTPUT} // see cli.ContainerAttach() method for more info. -func multiplexedForwardLogs(logPipe io.Reader) { +func (bp *DockerBuildProcessor) multiplexedForwardLogs(logPipe io.Reader) { hdr := make([]byte, 8) for { // Load size of message @@ -417,7 +417,7 @@ func multiplexedForwardLogs(logPipe io.Reader) { break } if err != nil { - slog.With("err", err.Error()).Error("log pipe error") + bp.Logger.Error("log pipe error", bp.Logger.Args("err", err.Error())) return } count := binary.BigEndian.Uint32(hdr[4:]) @@ -432,11 +432,11 @@ func multiplexedForwardLogs(logPipe io.Reader) { if uint32(readCnt) == count { break } - slog.With("err", err.Error()).Error("log pipe error") + bp.Logger.Error("log pipe error", bp.Logger.Args("err", io.EOF.Error())) return } if err != nil { - slog.With("err", err.Error()).Error("log pipe error") + bp.Logger.Error("log pipe error", bp.Logger.Args("err", err.Error())) return } } @@ -445,9 +445,9 @@ func multiplexedForwardLogs(logPipe io.Reader) { lines := strings.Split(string(dat), "\n") for _, line := range lines { if line != "" { - slog.Debug(line) + bp.Logger.Debug(line) } } } - slog.Debug("log pipe close") + bp.Logger.Debug("log pipe close") } diff --git a/pkg/driverbuilder/kubernetes.go b/pkg/driverbuilder/kubernetes.go index 793d2a7e..66d1a711 100644 --- a/pkg/driverbuilder/kubernetes.go +++ b/pkg/driverbuilder/kubernetes.go @@ -20,7 +20,8 @@ import ( "encoding/base64" "errors" "fmt" - "log/slog" + "github.com/falcosecurity/falcoctl/pkg/output" + "k8s.io/cli-runtime/pkg/genericiooptions" "os" "time" @@ -50,13 +51,21 @@ type KubernetesBuildProcessor struct { imagePullSecret string timeout int proxy string + *output.Printer } // NewKubernetesBuildProcessor constructs a KubernetesBuildProcessor // starting from a kubernetes.Clientset. bufferSize represents the length of the // channel we use to do the builds. A bigger bufferSize will mean that we can save more Builds // for processing, however setting this to a big value will have impacts -func NewKubernetesBuildProcessor(corev1Client v1.CoreV1Interface, clientConfig *restclient.Config, runAsUser int64, namespace string, imagePullSecret string, timeout int, proxy string) *KubernetesBuildProcessor { +func NewKubernetesBuildProcessor(corev1Client v1.CoreV1Interface, + clientConfig *restclient.Config, + runAsUser int64, + namespace string, + imagePullSecret string, + timeout int, + proxy string, +) *KubernetesBuildProcessor { return &KubernetesBuildProcessor{ coreV1Client: corev1Client, clientConfig: clientConfig, @@ -73,11 +82,8 @@ func (bp *KubernetesBuildProcessor) String() string { } func (bp *KubernetesBuildProcessor) Start(b *builder.Build) error { - slog.Debug("doing a new kubernetes build") - return bp.buildModule(b) -} + bp.Printer = b.Printer -func (bp *KubernetesBuildProcessor) buildModule(b *builder.Build) error { deadline := int64(bp.timeout) namespace := bp.namespace uid := uuid.NewUUID() @@ -101,7 +107,7 @@ func (bp *KubernetesBuildProcessor) buildModule(b *builder.Build) error { return err } - kernelDownloadScript, err := builder.KernelDownloadScript(v, c.KernelUrls, kr) + kernelDownloadScript, err := builder.KernelDownloadScript(v, c.KernelUrls, kr, bp.Printer) if err != nil { return err } @@ -237,9 +243,8 @@ func (bp *KubernetesBuildProcessor) buildModule(b *builder.Build) error { }, } - slog. - With("name", pod.Name, "spec", pod.Spec.String()). - Debug("starting pod") + bp.Logger.Debug("starting pod", + bp.Logger.Args("name", pod.Name, "spec", pod.Spec.String())) ctx := context.Background() ctx = signals.WithStandardSignals(ctx) @@ -276,33 +281,35 @@ func (bp *KubernetesBuildProcessor) copyModuleAndProbeFromPodWithUID(ctx context event := <-watch.ResultChan() p, ok := event.Object.(*corev1.Pod) if !ok { - slog.Error("unexpected type when watching pods") + bp.Logger.Error("unexpected type when watching pods") continue } if p.Status.Phase == corev1.PodPending { continue } if p.Status.Phase == corev1.PodRunning { - slog.With(falcoBuilderUIDLabel, falcoBuilderUID).Info("start downloading module and probe from pod") + bp.Logger.Info("start downloading module and probe from pod", + bp.Logger.Args(falcoBuilderUIDLabel, falcoBuilderUID)) if c.ModuleFilePath != "" { err = copySingleFileFromPod(c.ModuleFilePath, bp.coreV1Client, bp.clientConfig, p.Namespace, p.Name, c.ToDriverFullPath(), moduleLockFile) if err != nil { return err } - slog.Info("Kernel Module extraction successful") + bp.Logger.Info("Kernel Module extraction successful") } if c.ProbeFilePath != "" { err = copySingleFileFromPod(c.ProbeFilePath, bp.coreV1Client, bp.clientConfig, p.Namespace, p.Name, c.ToProbeFullPath(), probeLockFile) if err != nil { return err } - slog.Info("Probe Module extraction successful") + bp.Logger.Info("Probe Module extraction successful") } err = unlockPod(bp.coreV1Client, bp.clientConfig, p) if err != nil { return err } - slog.With(falcoBuilderUIDLabel, falcoBuilderUID).Info("completed downloading from pod") + bp.Logger.Info("completed downloading from pod", + bp.Logger.Args(falcoBuilderUIDLabel, falcoBuilderUID)) } return nil } @@ -314,7 +321,7 @@ func unlockPod(podClient v1.PodsGetter, clientConfig *restclient.Config, pod *co PodClient: podClient, Config: clientConfig, StreamOptions: exec.StreamOptions{ - IOStreams: genericclioptions.IOStreams{ + IOStreams: genericiooptions.IOStreams{ Out: bytes.NewBuffer([]byte{}), ErrOut: bytes.NewBuffer([]byte{}), }, diff --git a/pkg/driverbuilder/local.go b/pkg/driverbuilder/local.go index 6ab34133..f1e8a126 100644 --- a/pkg/driverbuilder/local.go +++ b/pkg/driverbuilder/local.go @@ -8,8 +8,8 @@ import ( "errors" "fmt" "github.com/falcosecurity/driverkit/pkg/driverbuilder/builder" + "github.com/falcosecurity/falcoctl/pkg/output" "io" - "log/slog" "os" "os/exec" "os/user" @@ -23,20 +23,25 @@ const ( ) type LocalBuildProcessor struct { - timeout int useDKMS bool downloadHeaders bool srcDir string envMap map[string]string + timeout int + *output.Printer } -func NewLocalBuildProcessor(timeout int, useDKMS, downloadHeaders bool, srcDir string, envMap map[string]string) *LocalBuildProcessor { +func NewLocalBuildProcessor(useDKMS, downloadHeaders bool, + srcDir string, + envMap map[string]string, + timeout int, +) *LocalBuildProcessor { return &LocalBuildProcessor{ - timeout: timeout, useDKMS: useDKMS, srcDir: srcDir, envMap: envMap, downloadHeaders: downloadHeaders, + timeout: timeout, } } @@ -45,8 +50,7 @@ func (lbp *LocalBuildProcessor) String() string { } func (lbp *LocalBuildProcessor) Start(b *builder.Build) error { - slog.Debug("doing a new local build") - + lbp.Printer = b.Printer if lbp.useDKMS { currentUser, err := user.Current() if err != nil { @@ -67,8 +71,8 @@ func (lbp *LocalBuildProcessor) Start(b *builder.Build) error { // if an unsupported target is passed. // Go on skipping automatic kernel headers download. if err == nil { - slog.Info("Trying automatic kernel headers download") - kernelDownloadScript, err := builder.KernelDownloadScript(realBuilder, nil, kr) + lbp.Logger.Info("Trying automatic kernel headers download") + kernelDownloadScript, err := builder.KernelDownloadScript(realBuilder, nil, kr, lbp.Printer) // Patch kernel download script to echo KERNELDIR. // We need to capture KERNELDIR to later pass it as env variable to the build. kernelDownloadScript += "\necho $KERNELDIR" @@ -83,7 +87,7 @@ func (lbp *LocalBuildProcessor) Start(b *builder.Build) error { for scanner.Scan() { path = scanner.Text() } - slog.Info("Setting KERNELDIR env var", "path", path) + lbp.Logger.Info("Setting KERNELDIR env var", lbp.Logger.Args("path", path)) // add the kerneldir path to env lbp.envMap[kernelDirEnv] = path defer func() { @@ -91,11 +95,11 @@ func (lbp *LocalBuildProcessor) Start(b *builder.Build) error { _ = os.RemoveAll(path) }() } else { - slog.Warn("Failed to download headers", "err", err) + lbp.Logger.Warn("Failed to download headers", lbp.Logger.Args("err", err)) } } } else { - slog.Info("Skipping kernel headers automatic download", "err", err) + lbp.Logger.Info("Skipping kernel headers automatic download", lbp.Logger.Args("err", err)) } } @@ -148,7 +152,7 @@ func (lbp *LocalBuildProcessor) Start(b *builder.Build) error { srcProbePath := vv.GetProbeFullPath(c) if len(lbp.srcDir) == 0 { - slog.Info("Downloading driver sources") + lbp.Logger.Info("Downloading driver sources") // Download src! libsDownloadScript, err := builder.LibsDownloadScript(c) if err != nil { @@ -179,14 +183,14 @@ func (lbp *LocalBuildProcessor) Start(b *builder.Build) error { stdout, err := cmd.StdoutPipe() if err != nil { - slog.Warn("Failed to pipe stdout", "err", err) + lbp.Logger.Warn("Failed to pipe stdout", lbp.Logger.Args("err", err)) _, err = cmd.CombinedOutput() } else { cmd.Stderr = cmd.Stdout // redirect stderr to stdout so that we catch it defer stdout.Close() err = cmd.Start() if err != nil { - slog.Warn("Failed to execute command", "err", err) + lbp.Logger.Warn("Failed to execute command", lbp.Logger.Args("err", err)) } else { // print the output of the subprocess line by line scanner := bufio.NewScanner(stdout) @@ -204,7 +208,7 @@ func (lbp *LocalBuildProcessor) Start(b *builder.Build) error { if err = copyDataToLocalPath(srcProbePath, b.ProbeFilePath); err != nil { return err } - slog.With("path", b.ProbeFilePath).Info("eBPF probe available") + lbp.Logger.Info("eBPF probe available", lbp.Logger.Args("path", b.ProbeFilePath)) c.ProbeFilePath = "" } } @@ -229,7 +233,7 @@ func (lbp *LocalBuildProcessor) Start(b *builder.Build) error { if err = copyDataToLocalPath(koFiles[0], b.ModuleFilePath); err != nil { return err } - slog.With("path", b.ModuleFilePath).Info("kernel module available") + lbp.Logger.Info("kernel module available", lbp.Logger.Args("path", b.ModuleFilePath)) } return nil } diff --git a/validate/isloglevel.go b/validate/isloglevel.go deleted file mode 100644 index c3244082..00000000 --- a/validate/isloglevel.go +++ /dev/null @@ -1,32 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -/* -Copyright (C) 2023 The Falco Authors. -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package validate - -import ( - "log/slog" - - "github.com/go-playground/validator/v10" -) - -var ProgramLevel = new(slog.LevelVar) - -func isLogLevel(fl validator.FieldLevel) bool { - level := fl.Field().String() - err := ProgramLevel.UnmarshalText([]byte(level)) - if err != nil { - return false - } - return true -} diff --git a/validate/validate.go b/validate/validate.go index 02abd945..7de87c5e 100644 --- a/validate/validate.go +++ b/validate/validate.go @@ -48,7 +48,6 @@ func init() { return name }) - V.RegisterValidation("loglevel", isLogLevel) V.RegisterValidation("filepath", isFilePath) V.RegisterValidation("sha1", isSHA1) V.RegisterValidation("target", isTargetSupported) @@ -154,19 +153,6 @@ func init() { }, ) - V.RegisterTranslation( - "loglevel", - T, - func(ut ut.Translator) error { - return ut.Add("loglevel", "{0} must be a valid slog level", true) - }, - func(ut ut.Translator, fe validator.FieldError) string { - t, _ := ut.T("loglevel", fe.Field()) - - return t - }, - ) - V.RegisterTranslation( "eq=dev|sha1|semver", T, From 8c6a73bb477147a681501944d6b72cd5fa69c6fa Mon Sep 17 00:00:00 2001 From: Federico Di Pierro Date: Thu, 11 Apr 2024 11:22:03 +0200 Subject: [PATCH 2/5] chore(cmd,pkg): small improvements and initial test fixes. Signed-off-by: Federico Di Pierro --- cmd/cli_test.go | 10 +++++--- cmd/config_options.go | 33 ++++++++++++++----------- cmd/docker.go | 4 +-- cmd/kubernetes.go | 6 ++--- cmd/kubernetes_in_cluster.go | 6 ++--- cmd/local.go | 4 +-- pkg/driverbuilder/builder/image_test.go | 10 ++++++-- 7 files changed, 44 insertions(+), 29 deletions(-) diff --git a/cmd/cli_test.go b/cmd/cli_test.go index b639d06d..9b734c98 100644 --- a/cmd/cli_test.go +++ b/cmd/cli_test.go @@ -315,9 +315,13 @@ var tests = []testCase{ func run(t *testing.T, test testCase) { // Setup - c := NewRootCmd() + configOpts, err := NewConfigOptions() + assert.NilError(t, err) + rootOpts, err := NewRootOptions() + assert.NilError(t, err) + c := NewRootCmd(configOpts, rootOpts) b := bytes.NewBufferString("") - c.SetOutput(b) + configOpts.SetOutput(b) if len(test.args) == 0 || (test.args[0] != "__complete" && test.args[0] != "__completeNoDesc" && test.args[0] != "help" && test.args[0] != "completion") { test.args = append(test.args, "--dryrun") } @@ -328,7 +332,7 @@ func run(t *testing.T, test testCase) { } } // Test - err := c.Execute() + err = c.Execute() if err != nil { if test.expect.err == "" { t.Fatalf("error executing CLI: %v", err) diff --git a/cmd/config_options.go b/cmd/config_options.go index 76affe18..6173c2d6 100644 --- a/cmd/config_options.go +++ b/cmd/config_options.go @@ -37,27 +37,32 @@ var aliasProcessors = []string{"docker", "k8s", "k8s-ic"} // ConfigOptions represent the persistent configuration flags of driverkit. type ConfigOptions struct { - ConfigFile string - Timeout int `validate:"number,min=30" default:"120" name:"timeout"` - ProxyURL string `validate:"omitempty,proxy" name:"proxy url"` - DryRun bool + configFile string + timeout int `validate:"number,min=30" default:"120" name:"timeout"` + proxyURL string `validate:"omitempty,proxy" name:"proxy url"` + dryRun bool // Printer used by all commands to output messages. Printer *output.Printer - // Writer is used to write the output of the printer. - Writer io.Writer + // writer is used to write the output of the printer. + writer io.Writer logLevel *options.LogLevel } func (co *ConfigOptions) initPrinter() { logLevel := co.logLevel.ToPtermLogLevel() - co.Printer = output.NewPrinter(logLevel, pterm.LogFormatterColorful, co.Writer) + co.Printer = output.NewPrinter(logLevel, pterm.LogFormatterColorful, co.writer) +} + +func (co *ConfigOptions) SetOutput(writer io.Writer) { + co.writer = writer + co.initPrinter() } // NewConfigOptions creates an instance of ConfigOptions. func NewConfigOptions() (*ConfigOptions, error) { o := &ConfigOptions{ - Writer: os.Stdout, + writer: os.Stdout, logLevel: options.NewLogLevel(), } o.initPrinter() @@ -85,11 +90,11 @@ func (co *ConfigOptions) validate() []error { // AddFlags registers the common flags. func (co *ConfigOptions) AddFlags(flags *pflag.FlagSet) { - flags.StringVarP(&co.ConfigFile, "config", "c", co.ConfigFile, "config file path (default $HOME/.driverkit.yaml if exists)") + flags.StringVarP(&co.configFile, "config", "c", co.configFile, "config file path (default $HOME/.driverkit.yaml if exists)") flags.VarP(co.logLevel, "loglevel", "l", "Set level for logs "+co.logLevel.Allowed()) - flags.IntVar(&co.Timeout, "timeout", co.Timeout, "timeout in seconds") - flags.StringVar(&co.ProxyURL, "proxy", co.ProxyURL, "the proxy to use to download data") - flags.BoolVar(&co.DryRun, "dryrun", co.DryRun, "do not actually perform the action") + flags.IntVar(&co.timeout, "timeout", co.timeout, "timeout in seconds") + flags.StringVar(&co.proxyURL, "proxy", co.proxyURL, "the proxy to use to download data") + flags.BoolVar(&co.dryRun, "dryrun", co.dryRun, "do not actually perform the action") } // Init reads in config file and ENV variables if set. @@ -102,8 +107,8 @@ func (co *ConfigOptions) Init() bool { } configErr = true } - if co.ConfigFile != "" { - viper.SetConfigFile(co.ConfigFile) + if co.configFile != "" { + viper.SetConfigFile(co.configFile) } else { // Find home directory. home, err := homedir.Dir() diff --git a/cmd/docker.go b/cmd/docker.go index ac737a13..9a50cd20 100644 --- a/cmd/docker.go +++ b/cmd/docker.go @@ -29,7 +29,7 @@ func NewDockerCmd(configOpts *ConfigOptions, rootOpts *RootOptions, rootFlags *p RunE: func(c *cobra.Command, args []string) error { configOpts.Printer.Logger.Info("starting build", configOpts.Printer.Logger.Args("processor", c.Name())) - if !configOpts.DryRun { + if !configOpts.dryRun { // Since we use a spinner, cache log data to a bytesbuffer; // we will later print it once we stop the spinner. var buf bytes.Buffer @@ -44,7 +44,7 @@ func NewDockerCmd(configOpts *ConfigOptions, rootOpts *RootOptions, rootFlags *p defer func() { _ = configOpts.Printer.Spinner.Stop() }() - return driverbuilder.NewDockerBuildProcessor(configOpts.Timeout, configOpts.ProxyURL).Start(b) + return driverbuilder.NewDockerBuildProcessor(configOpts.timeout, configOpts.proxyURL).Start(b) } return nil }, diff --git a/cmd/kubernetes.go b/cmd/kubernetes.go index 53d1f7d1..69bf2295 100644 --- a/cmd/kubernetes.go +++ b/cmd/kubernetes.go @@ -60,7 +60,7 @@ func NewKubernetesCmd(configOpts *ConfigOptions, rootOpts *RootOptions, rootFlag kubernetesCmd.RunE = func(c *cobra.Command, args []string) error { configOpts.Printer.Logger.Info("starting build", configOpts.Printer.Logger.Args("processor", c.Name())) - if !configOpts.DryRun { + if !configOpts.dryRun { // Since we use a spinner, cache log data to a bytesbuffer; // we will later print it once we stop the spinner. var buf bytes.Buffer @@ -104,7 +104,7 @@ func kubernetesRun(kubefactory factory.Factory, kubernetesOptions.RunAsUser, kubernetesOptions.Namespace, kubernetesOptions.ImagePullSecret, - configOpts.Timeout, - configOpts.ProxyURL) + configOpts.timeout, + configOpts.proxyURL) return buildProcessor.Start(b) } diff --git a/cmd/kubernetes_in_cluster.go b/cmd/kubernetes_in_cluster.go index d1d57310..310dc677 100644 --- a/cmd/kubernetes_in_cluster.go +++ b/cmd/kubernetes_in_cluster.go @@ -43,7 +43,7 @@ func NewKubernetesInClusterCmd(configOpts *ConfigOptions, rootOpts *RootOptions, kubernetesInClusterCmd.RunE = func(c *cobra.Command, args []string) error { configOpts.Printer.Logger.Info("starting build", configOpts.Printer.Logger.Args("processor", c.Name())) - if !configOpts.DryRun { + if !configOpts.dryRun { // Since we use a spinner, cache log data to a bytesbuffer; // we will later print it once we stop the spinner. var buf bytes.Buffer @@ -85,7 +85,7 @@ func kubernetesInClusterRun(b *builder.Build, configOpts *ConfigOptions) error { kubernetesOptions.RunAsUser, kubernetesOptions.Namespace, kubernetesOptions.ImagePullSecret, - configOpts.Timeout, - configOpts.ProxyURL) + configOpts.timeout, + configOpts.proxyURL) return buildProcessor.Start(b) } diff --git a/cmd/local.go b/cmd/local.go index 1d48e215..b16fbb72 100644 --- a/cmd/local.go +++ b/cmd/local.go @@ -23,7 +23,7 @@ func NewLocalCmd(configOpts *ConfigOptions, rootOpts *RootOptions, rootFlags *pf RunE: func(c *cobra.Command, args []string) error { configOpts.Printer.Logger.Info("starting build", configOpts.Printer.Logger.Args("processor", c.Name())) - if !configOpts.DryRun { + if !configOpts.dryRun { // Since we use a spinner, cache log data to a bytesbuffer; // we will later print it once we stop the spinner. var buf bytes.Buffer @@ -42,7 +42,7 @@ func NewLocalCmd(configOpts *ConfigOptions, rootOpts *RootOptions, rootFlags *pf opts.downloadHeaders, opts.srcDir, opts.envMap, - configOpts.Timeout).Start(b) + configOpts.timeout).Start(b) } return nil }, diff --git a/pkg/driverbuilder/builder/image_test.go b/pkg/driverbuilder/builder/image_test.go index a1d848e4..be3d7b5e 100644 --- a/pkg/driverbuilder/builder/image_test.go +++ b/pkg/driverbuilder/builder/image_test.go @@ -15,6 +15,8 @@ limitations under the License. package builder import ( + "github.com/falcosecurity/falcoctl/pkg/output" + "github.com/pterm/pterm" "io" "net/http" "os" @@ -236,6 +238,8 @@ images: } func TestFileImagesLister(t *testing.T) { + printer := output.NewPrinter(pterm.LogLevelInfo, pterm.LogFormatterColorful, os.Stdout) + // setup images file f, err := os.CreateTemp(t.TempDir(), "imagetest") if err != nil { @@ -269,11 +273,13 @@ func TestFileImagesLister(t *testing.T) { t.Fatal(err) } - assert.DeepEqual(t, test.expected, lister.LoadImages()) + assert.DeepEqual(t, test.expected, lister.LoadImages(printer)) } } func TestRepoImagesLister(t *testing.T) { + printer := output.NewPrinter(pterm.LogLevelInfo, pterm.LogFormatterColorful, os.Stdout) + mock, err := registry.NewMock(t) assert.NilError(t, err) defer mock.Close() @@ -300,6 +306,6 @@ func TestRepoImagesLister(t *testing.T) { mock.RegisterHandler("/v2/foo/test/tags/list", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte(test.jsonData)) }) - assert.DeepEqual(t, test.expected, lister.LoadImages()) + assert.DeepEqual(t, test.expected, lister.LoadImages(printer)) } } From 589ad278355579ff6b8b6c38cabb34535b87542d Mon Sep 17 00:00:00 2001 From: Federico Di Pierro Date: Thu, 11 Apr 2024 12:18:03 +0200 Subject: [PATCH 3/5] chore(cmd,pkg): allow cli test to disable styling. Signed-off-by: Federico Di Pierro --- cmd/cli_test.go | 12 ++++-------- cmd/completion.go | 16 +++++++--------- cmd/config_options.go | 28 +++++++++++++++++----------- cmd/docker.go | 28 ++++++++++++++++------------ cmd/images.go | 23 +++++++++++++++++------ cmd/kubernetes.go | 29 ++++++++++++++++------------- cmd/kubernetes_in_cluster.go | 29 ++++++++++++++++------------- cmd/local.go | 28 ++++++++++++++++------------ cmd/root.go | 12 ++++++++++-- cmd/root_options.go | 4 ++++ pkg/driverbuilder/builder/build.go | 4 ---- 11 files changed, 123 insertions(+), 90 deletions(-) diff --git a/cmd/cli_test.go b/cmd/cli_test.go index 9b734c98..7064a200 100644 --- a/cmd/cli_test.go +++ b/cmd/cli_test.go @@ -19,7 +19,6 @@ package cmd import ( "bytes" - "io" "io/ioutil" "os" "path/filepath" @@ -319,9 +318,9 @@ func run(t *testing.T, test testCase) { assert.NilError(t, err) rootOpts, err := NewRootOptions() assert.NilError(t, err) + var buf bytes.Buffer + configOpts.setOutput(&buf, true) c := NewRootCmd(configOpts, rootOpts) - b := bytes.NewBufferString("") - configOpts.SetOutput(b) if len(test.args) == 0 || (test.args[0] != "__complete" && test.args[0] != "__completeNoDesc" && test.args[0] != "help" && test.args[0] != "completion") { test.args = append(test.args, "--dryrun") } @@ -340,11 +339,8 @@ func run(t *testing.T, test testCase) { assert.Error(t, err, test.expect.err) } } - out, err := io.ReadAll(b) - if err != nil { - t.Fatalf("error reading CLI output: %v", err) - } - res := stripansi.Strip(string(out)) + out := buf.String() + res := stripansi.Strip(out) assert.Equal(t, test.expect.out, res) // Teardown for k := range test.env { diff --git a/cmd/completion.go b/cmd/completion.go index b1199cad..1675e337 100644 --- a/cmd/completion.go +++ b/cmd/completion.go @@ -66,25 +66,23 @@ func NewCompletionCmd(_ *ConfigOptions, _ *RootOptions, _ *pflag.FlagSet) *cobra Args: validateArgs(), ValidArgs: cmdArgs, DisableAutoGenTag: true, - Run: func(c *cobra.Command, args []string) { + RunE: func(c *cobra.Command, args []string) error { if len(args) == 0 { - c.Help() - return + return c.Help() } arg := args[0] switch arg { case "bash": - c.Root().GenBashCompletion(os.Stdout) - break + return c.Root().GenBashCompletion(os.Stdout) case "zsh": - c.Root().GenZshCompletion(os.Stdout) - break + return c.Root().GenZshCompletion(os.Stdout) case "fish": - c.Root().GenFishCompletion(os.Stdout, true) + return c.Root().GenFishCompletion(os.Stdout, true) case "help": - c.Help() + return c.Help() } + return nil }, } diff --git a/cmd/config_options.go b/cmd/config_options.go index 6173c2d6..5a2237f1 100644 --- a/cmd/config_options.go +++ b/cmd/config_options.go @@ -38,32 +38,38 @@ var aliasProcessors = []string{"docker", "k8s", "k8s-ic"} // ConfigOptions represent the persistent configuration flags of driverkit. type ConfigOptions struct { configFile string - timeout int `validate:"number,min=30" default:"120" name:"timeout"` - proxyURL string `validate:"omitempty,proxy" name:"proxy url"` + Timeout int `validate:"number,min=30" default:"120" name:"timeout"` + ProxyURL string `validate:"omitempty,proxy" name:"proxy url"` dryRun bool // Printer used by all commands to output messages. Printer *output.Printer // writer is used to write the output of the printer. - writer io.Writer - logLevel *options.LogLevel + writer io.Writer + logLevel *options.LogLevel + disableStyling bool } func (co *ConfigOptions) initPrinter() { - logLevel := co.logLevel.ToPtermLogLevel() - co.Printer = output.NewPrinter(logLevel, pterm.LogFormatterColorful, co.writer) + if co.disableStyling { + pterm.DisableColor() + } + co.Printer = output.NewPrinter(co.logLevel.ToPtermLogLevel(), pterm.LogFormatterColorful, co.writer) } -func (co *ConfigOptions) SetOutput(writer io.Writer) { +// Called by tests to disable styling and set bytes buffer as output +func (co *ConfigOptions) setOutput(writer io.Writer, disableStyling bool) { co.writer = writer + co.disableStyling = disableStyling co.initPrinter() } // NewConfigOptions creates an instance of ConfigOptions. func NewConfigOptions() (*ConfigOptions, error) { o := &ConfigOptions{ - writer: os.Stdout, - logLevel: options.NewLogLevel(), + writer: os.Stdout, + logLevel: options.NewLogLevel(), + disableStyling: false, } o.initPrinter() if err := defaults.Set(o); err != nil { @@ -92,8 +98,8 @@ func (co *ConfigOptions) validate() []error { func (co *ConfigOptions) AddFlags(flags *pflag.FlagSet) { flags.StringVarP(&co.configFile, "config", "c", co.configFile, "config file path (default $HOME/.driverkit.yaml if exists)") flags.VarP(co.logLevel, "loglevel", "l", "Set level for logs "+co.logLevel.Allowed()) - flags.IntVar(&co.timeout, "timeout", co.timeout, "timeout in seconds") - flags.StringVar(&co.proxyURL, "proxy", co.proxyURL, "the proxy to use to download data") + flags.IntVar(&co.Timeout, "timeout", co.Timeout, "timeout in seconds") + flags.StringVar(&co.ProxyURL, "proxy", co.ProxyURL, "the proxy to use to download data") flags.BoolVar(&co.dryRun, "dryrun", co.dryRun, "do not actually perform the action") } diff --git a/cmd/docker.go b/cmd/docker.go index 9a50cd20..a99e9f6b 100644 --- a/cmd/docker.go +++ b/cmd/docker.go @@ -17,6 +17,7 @@ package cmd import ( "bytes" "github.com/falcosecurity/driverkit/pkg/driverbuilder" + "github.com/falcosecurity/driverkit/pkg/driverbuilder/builder" "github.com/spf13/cobra" "github.com/spf13/pflag" ) @@ -30,21 +31,24 @@ func NewDockerCmd(configOpts *ConfigOptions, rootOpts *RootOptions, rootFlags *p configOpts.Printer.Logger.Info("starting build", configOpts.Printer.Logger.Args("processor", c.Name())) if !configOpts.dryRun { + if !rootOpts.Output.HasOutputs() { + configOpts.Printer.Logger.Info("no output specified") + return nil + } // Since we use a spinner, cache log data to a bytesbuffer; // we will later print it once we stop the spinner. - var buf bytes.Buffer - b := rootOpts.ToBuild(configOpts.Printer.WithWriter(&buf)) - defer func() { - configOpts.Printer.DefaultText.Print(buf.String()) - }() - if !b.HasOutputs() { - return nil + var b *builder.Build + if configOpts.disableStyling { + b = rootOpts.ToBuild(configOpts.Printer) + } else { + var buf bytes.Buffer + b = rootOpts.ToBuild(configOpts.Printer.WithWriter(&buf)) + configOpts.Printer.Spinner, _ = configOpts.Printer.Spinner.Start("driver building, it will take a few seconds") + defer func() { + configOpts.Printer.DefaultText.Print(buf.String()) + }() } - configOpts.Printer.Spinner, _ = configOpts.Printer.Spinner.Start("driver building, it will take a few seconds") - defer func() { - _ = configOpts.Printer.Spinner.Stop() - }() - return driverbuilder.NewDockerBuildProcessor(configOpts.timeout, configOpts.proxyURL).Start(b) + return driverbuilder.NewDockerBuildProcessor(configOpts.Timeout, configOpts.ProxyURL).Start(b) } return nil }, diff --git a/cmd/images.go b/cmd/images.go index e8507fe0..4fcdb823 100644 --- a/cmd/images.go +++ b/cmd/images.go @@ -16,6 +16,7 @@ package cmd import ( "bytes" + "github.com/falcosecurity/driverkit/pkg/driverbuilder/builder" "os" "github.com/olekukonko/tablewriter" @@ -28,17 +29,26 @@ func NewImagesCmd(configOpts *ConfigOptions, rootOpts *RootOptions, rootFlags *p imagesCmd := &cobra.Command{ Use: "images", Short: "List builder images", - Run: func(c *cobra.Command, args []string) { + RunE: func(c *cobra.Command, args []string) error { configOpts.Printer.Logger.Info("starting loading images", configOpts.Printer.Logger.Args("processor", c.Name())) // Since we use a spinner, cache log data to a bytesbuffer; // we will later print it once we stop the spinner. - var buf bytes.Buffer - b := rootOpts.ToBuild(configOpts.Printer.WithWriter(&buf)) - configOpts.Printer.Spinner, _ = configOpts.Printer.Spinner.Start("listing images, it will take a few seconds") + var ( + buf bytes.Buffer + b *builder.Build + ) + if configOpts.disableStyling { + b = rootOpts.ToBuild(configOpts.Printer) + } else { + b = rootOpts.ToBuild(configOpts.Printer.WithWriter(&buf)) + configOpts.Printer.Spinner, _ = configOpts.Printer.Spinner.Start("listing images, it will take a few seconds") + } b.LoadImages() - _ = configOpts.Printer.Spinner.Stop() - configOpts.Printer.DefaultText.Print(buf.String()) + if !configOpts.disableStyling { + _ = configOpts.Printer.Spinner.Stop() + configOpts.Printer.DefaultText.Print(buf.String()) + } table := tablewriter.NewWriter(os.Stdout) table.SetHeader([]string{"Image", "Target", "Arch", "GCC"}) @@ -54,6 +64,7 @@ func NewImagesCmd(configOpts *ConfigOptions, rootOpts *RootOptions, rootFlags *p table.Append(data) } table.Render() // Send output + return nil }, } // Add root flags diff --git a/cmd/kubernetes.go b/cmd/kubernetes.go index 69bf2295..0859543f 100644 --- a/cmd/kubernetes.go +++ b/cmd/kubernetes.go @@ -61,20 +61,23 @@ func NewKubernetesCmd(configOpts *ConfigOptions, rootOpts *RootOptions, rootFlag configOpts.Printer.Logger.Info("starting build", configOpts.Printer.Logger.Args("processor", c.Name())) if !configOpts.dryRun { + if !rootOpts.Output.HasOutputs() { + configOpts.Printer.Logger.Info("no output specified") + return nil + } // Since we use a spinner, cache log data to a bytesbuffer; // we will later print it once we stop the spinner. - var buf bytes.Buffer - b := rootOpts.ToBuild(configOpts.Printer.WithWriter(&buf)) - defer func() { - configOpts.Printer.DefaultText.Print(buf.String()) - }() - if !b.HasOutputs() { - return nil + var b *builder.Build + if configOpts.disableStyling { + b = rootOpts.ToBuild(configOpts.Printer) + } else { + var buf bytes.Buffer + b = rootOpts.ToBuild(configOpts.Printer.WithWriter(&buf)) + configOpts.Printer.Spinner, _ = configOpts.Printer.Spinner.Start("driver building, it will take a few seconds") + defer func() { + configOpts.Printer.DefaultText.Print(buf.String()) + }() } - configOpts.Printer.Spinner, _ = configOpts.Printer.Spinner.Start("driver building, it will take a few seconds") - defer func() { - _ = configOpts.Printer.Spinner.Stop() - }() return kubernetesRun(kubefactory, b, configOpts) } return nil @@ -104,7 +107,7 @@ func kubernetesRun(kubefactory factory.Factory, kubernetesOptions.RunAsUser, kubernetesOptions.Namespace, kubernetesOptions.ImagePullSecret, - configOpts.timeout, - configOpts.proxyURL) + configOpts.Timeout, + configOpts.ProxyURL) return buildProcessor.Start(b) } diff --git a/cmd/kubernetes_in_cluster.go b/cmd/kubernetes_in_cluster.go index 310dc677..31a1e81f 100644 --- a/cmd/kubernetes_in_cluster.go +++ b/cmd/kubernetes_in_cluster.go @@ -44,20 +44,23 @@ func NewKubernetesInClusterCmd(configOpts *ConfigOptions, rootOpts *RootOptions, configOpts.Printer.Logger.Info("starting build", configOpts.Printer.Logger.Args("processor", c.Name())) if !configOpts.dryRun { + if !rootOpts.Output.HasOutputs() { + configOpts.Printer.Logger.Info("no output specified") + return nil + } // Since we use a spinner, cache log data to a bytesbuffer; // we will later print it once we stop the spinner. - var buf bytes.Buffer - b := rootOpts.ToBuild(configOpts.Printer.WithWriter(&buf)) - defer func() { - configOpts.Printer.DefaultText.Print(buf.String()) - }() - if !b.HasOutputs() { - return nil + var b *builder.Build + if configOpts.disableStyling { + b = rootOpts.ToBuild(configOpts.Printer) + } else { + var buf bytes.Buffer + b = rootOpts.ToBuild(configOpts.Printer.WithWriter(&buf)) + configOpts.Printer.Spinner, _ = configOpts.Printer.Spinner.Start("driver building, it will take a few seconds") + defer func() { + configOpts.Printer.DefaultText.Print(buf.String()) + }() } - configOpts.Printer.Spinner, _ = configOpts.Printer.Spinner.Start("driver building, it will take a few seconds") - defer func() { - _ = configOpts.Printer.Spinner.Stop() - }() return kubernetesInClusterRun(b, configOpts) } return nil @@ -85,7 +88,7 @@ func kubernetesInClusterRun(b *builder.Build, configOpts *ConfigOptions) error { kubernetesOptions.RunAsUser, kubernetesOptions.Namespace, kubernetesOptions.ImagePullSecret, - configOpts.timeout, - configOpts.proxyURL) + configOpts.Timeout, + configOpts.ProxyURL) return buildProcessor.Start(b) } diff --git a/cmd/local.go b/cmd/local.go index b16fbb72..01c850d6 100644 --- a/cmd/local.go +++ b/cmd/local.go @@ -3,6 +3,7 @@ package cmd import ( "bytes" "github.com/falcosecurity/driverkit/pkg/driverbuilder" + "github.com/falcosecurity/driverkit/pkg/driverbuilder/builder" "github.com/spf13/cobra" "github.com/spf13/pflag" ) @@ -24,25 +25,28 @@ func NewLocalCmd(configOpts *ConfigOptions, rootOpts *RootOptions, rootFlags *pf configOpts.Printer.Logger.Info("starting build", configOpts.Printer.Logger.Args("processor", c.Name())) if !configOpts.dryRun { + if !rootOpts.Output.HasOutputs() { + configOpts.Printer.Logger.Info("no output specified") + return nil + } // Since we use a spinner, cache log data to a bytesbuffer; // we will later print it once we stop the spinner. - var buf bytes.Buffer - b := rootOpts.ToBuild(configOpts.Printer.WithWriter(&buf)) - defer func() { - configOpts.Printer.DefaultText.Print(buf.String()) - }() - if !b.HasOutputs() { - return nil + var b *builder.Build + if configOpts.disableStyling { + b = rootOpts.ToBuild(configOpts.Printer) + } else { + var buf bytes.Buffer + b = rootOpts.ToBuild(configOpts.Printer.WithWriter(&buf)) + configOpts.Printer.Spinner, _ = configOpts.Printer.Spinner.Start("driver building, it will take a few seconds") + defer func() { + configOpts.Printer.DefaultText.Print(buf.String()) + }() } - configOpts.Printer.Spinner, _ = configOpts.Printer.Spinner.Start("driver building, it will take a few seconds") - defer func() { - _ = configOpts.Printer.Spinner.Stop() - }() return driverbuilder.NewLocalBuildProcessor(opts.useDKMS, opts.downloadHeaders, opts.srcDir, opts.envMap, - configOpts.timeout).Start(b) + configOpts.Timeout).Start(b) } return nil }, diff --git a/cmd/root.go b/cmd/root.go index 3e52d10d..717f9c10 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -112,13 +112,14 @@ func NewRootCmd(configOpts *ConfigOptions, rootOpts *RootOptions) *RootCmd { Args: cobra.OnlyValidArgs, DisableFlagsInUseLine: true, DisableAutoGenTag: true, + SilenceUsage: true, Version: version.String(), - Run: func(c *cobra.Command, args []string) { + RunE: func(c *cobra.Command, args []string) error { if len(args) == 0 { configOpts.Printer.Logger.Info("specify a valid processor", configOpts.Printer.Logger.Args("processors", validProcessors)) } // Fallback to help - _ = c.Help() + return c.Help() }, } ret := &RootCmd{ @@ -210,6 +211,13 @@ func Start() { configOpts.Printer.Logger.Fatal("error setting driverkit root options defaults", configOpts.Printer.Logger.Args("err", err.Error())) } + + // Cleanup spinner upon leaving if any + defer func() { + if configOpts.Printer.Spinner != nil { + _ = configOpts.Printer.Spinner.Stop() + } + }() root := NewRootCmd(configOpts, rootOpts) if err = root.Execute(); err != nil { configOpts.Printer.Logger.Fatal("error executing driverkit", configOpts.Printer.Logger.Args("err", err.Error())) diff --git a/cmd/root_options.go b/cmd/root_options.go index efb064a7..e8fdae7e 100644 --- a/cmd/root_options.go +++ b/cmd/root_options.go @@ -36,6 +36,10 @@ type OutputOptions struct { Probe string `validate:"required_without=Module,filepath,omitempty,endswith=.o" name:"output probe path"` } +func (oo *OutputOptions) HasOutputs() bool { + return oo.Module != "" || oo.Probe != "" +} + type RepoOptions struct { Org string `default:"falcosecurity" name:"organization name"` Name string `default:"libs" name:"repo name"` diff --git a/pkg/driverbuilder/builder/build.go b/pkg/driverbuilder/builder/build.go index 6d0e8558..650b0a48 100644 --- a/pkg/driverbuilder/builder/build.go +++ b/pkg/driverbuilder/builder/build.go @@ -111,7 +111,3 @@ func (b *Build) ClientForRegistry(registry string) *auth.Client { return client } - -func (b *Build) HasOutputs() bool { - return b.ModuleFilePath != "" || b.ProbeFilePath != "" -} From 1b25d9cb7f64b26cb6051e6bef9ce1f32b261c7a Mon Sep 17 00:00:00 2001 From: Federico Di Pierro Date: Thu, 11 Apr 2024 14:11:50 +0200 Subject: [PATCH 4/5] chore(cmd,docs): updated docs and fixed cmd related tests. Moreover, moved cmd output to more strictly follow `falcoctl` one, with regards to printing usage/helper messages. Signed-off-by: Federico Di Pierro --- cmd/cli_test.go | 9 +++++++-- cmd/config_options.go | 17 +++++++++++++---- cmd/root.go | 14 ++++++++++++-- cmd/testdata/autohelp.txt | 3 ++- cmd/testdata/configs/1.yaml | 1 + cmd/testdata/configs/2.yaml | 1 + cmd/testdata/docker-from-config-debug.txt | 16 +++++++++++++--- .../docker-override-from-config-debug.txt | 16 +++++++++++++--- .../docker-override-urls-from-config-debug.txt | 16 +++++++++++++--- cmd/testdata/docker-related-target-debug.txt | 16 +++++++++++++--- ...ker-target-redhat-validation-error-debug.txt | 12 ++++-------- cmd/testdata/docker-with-flags-debug.txt | 16 +++++++++++++--- cmd/testdata/docker-with-flags.txt | 2 +- cmd/testdata/dockernoopts.txt | 17 +++++++---------- cmd/testdata/invalid-proxyconfig.txt | 14 +++----------- cmd/testdata/non-existent-processor.txt | 11 +---------- cmd/testdata/templates/flags.txt | 2 +- docs/driverkit.md | 2 +- docs/driverkit_docker.md | 2 +- docs/driverkit_images.md | 2 +- docs/driverkit_kubernetes-in-cluster.md | 2 +- docs/driverkit_kubernetes.md | 2 +- docs/driverkit_local.md | 2 +- 23 files changed, 124 insertions(+), 71 deletions(-) diff --git a/cmd/cli_test.go b/cmd/cli_test.go index 7064a200..949b78d3 100644 --- a/cmd/cli_test.go +++ b/cmd/cli_test.go @@ -19,7 +19,6 @@ package cmd import ( "bytes" - "io/ioutil" "os" "path/filepath" "runtime" @@ -131,6 +130,8 @@ var tests = []testCase{ "ubuntu-aws", "--output-module", "/tmp/falco-ubuntu-aws.ko", + "--output-probe", + "/tmp/falco-ubuntu-aws.o", "--loglevel", "debug", }, @@ -143,6 +144,7 @@ var tests = []testCase{ env: map[string]string{ "DRIVERKIT_KERNELVERSION": "59", "DRIVERKIT_OUTPUT_MODULE": "/tmp/falco-ubuntu-aws.ko", + "DRIVERKIT_OUTPUT_PROBE": "/tmp/falco-ubuntu-aws.o", }, args: []string{ "docker", @@ -321,6 +323,7 @@ func run(t *testing.T, test testCase) { var buf bytes.Buffer configOpts.setOutput(&buf, true) c := NewRootCmd(configOpts, rootOpts) + c.SetOutput(&buf) if len(test.args) == 0 || (test.args[0] != "__complete" && test.args[0] != "__completeNoDesc" && test.args[0] != "help" && test.args[0] != "completion") { test.args = append(test.args, "--dryrun") } @@ -338,6 +341,8 @@ func run(t *testing.T, test testCase) { } else { assert.Error(t, err, test.expect.err) } + // Exactly same behavior as rootCmd.Start(), but here we use ERROR instead of FATAL to avoid leaving + configOpts.Printer.Logger.Error("error executing driverkit", configOpts.Printer.Logger.Args("err", err.Error())) } out := buf.String() res := stripansi.Strip(out) @@ -365,7 +370,7 @@ type testTemplateData struct { } func readTemplateFile(t *testing.T, s string) string { - out, err := ioutil.ReadFile("testdata/templates/" + s) + out, err := os.ReadFile("testdata/templates/" + s) assert.NilError(t, err) return string(out) } diff --git a/cmd/config_options.go b/cmd/config_options.go index 5a2237f1..220931d2 100644 --- a/cmd/config_options.go +++ b/cmd/config_options.go @@ -51,10 +51,16 @@ type ConfigOptions struct { } func (co *ConfigOptions) initPrinter() { + // DisableStyling is only enforced by tests. if co.disableStyling { - pterm.DisableColor() + pterm.DisableStyling() } co.Printer = output.NewPrinter(co.logLevel.ToPtermLogLevel(), pterm.LogFormatterColorful, co.writer) + if co.disableStyling { + // Disable time print for tests + co.Printer.Logger = co.Printer.Logger.WithTime(false) + } + } // Called by tests to disable styling and set bytes buffer as output @@ -97,7 +103,7 @@ func (co *ConfigOptions) validate() []error { // AddFlags registers the common flags. func (co *ConfigOptions) AddFlags(flags *pflag.FlagSet) { flags.StringVarP(&co.configFile, "config", "c", co.configFile, "config file path (default $HOME/.driverkit.yaml if exists)") - flags.VarP(co.logLevel, "loglevel", "l", "Set level for logs "+co.logLevel.Allowed()) + flags.VarP(co.logLevel, "loglevel", "l", "set level for logs "+co.logLevel.Allowed()) flags.IntVar(&co.Timeout, "timeout", co.Timeout, "timeout in seconds") flags.StringVar(&co.ProxyURL, "proxy", co.ProxyURL, "the proxy to use to download data") flags.BoolVar(&co.dryRun, "dryrun", co.dryRun, "do not actually perform the action") @@ -133,7 +139,11 @@ func (co *ConfigOptions) Init() bool { viper.SetEnvKeyReplacer(strings.NewReplacer("-", "_")) // If a config file is found, read it in. - if err := viper.ReadInConfig(); err == nil { + err := viper.ReadInConfig() + // Init printer with either read or existent one, + // so that we can further log considering log level set. + co.initPrinter() + if err == nil { co.Printer.Logger.Info("using config file", co.Printer.Logger.Args("file", viper.ConfigFileUsed())) } else { @@ -143,6 +153,5 @@ func (co *ConfigOptions) Init() bool { co.Printer.Logger.Debug("running without a configuration file") } } - co.initPrinter() return configErr } diff --git a/cmd/root.go b/cmd/root.go index 717f9c10..6348575a 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -15,7 +15,9 @@ limitations under the License. package cmd import ( + "errors" "fmt" + "io" "os" "sort" "strings" @@ -31,10 +33,11 @@ import ( func persistentValidateFunc(rootCommand *RootCmd, configOpts *ConfigOptions, rootOpts *RootOptions) func(c *cobra.Command, args []string) error { return func(c *cobra.Command, args []string) error { + var validationError = errors.New("exiting for validation errors") configErr := configOpts.Init() // Early exit if detect some error into config flags if configErr { - return fmt.Errorf("exiting for validation errors") + return validationError } // Merge environment variables or config file values into the RootOptions instance skip := map[string]bool{ // do not merge these @@ -89,7 +92,7 @@ func persistentValidateFunc(rootCommand *RootCmd, configOpts *ConfigOptions, roo configOpts.Printer.Logger.Error("error validating build options", configOpts.Printer.Logger.Args("err", err.Error())) } - return fmt.Errorf("exiting for validation errors") + return validationError } rootOpts.Log(configOpts.Printer) } @@ -112,6 +115,7 @@ func NewRootCmd(configOpts *ConfigOptions, rootOpts *RootOptions) *RootCmd { Args: cobra.OnlyValidArgs, DisableFlagsInUseLine: true, DisableAutoGenTag: true, + SilenceErrors: true, SilenceUsage: true, Version: version.String(), RunE: func(c *cobra.Command, args []string) error { @@ -189,6 +193,12 @@ func (r *RootCmd) SetArgs(args []string) { r.c.SetArgs(args) } +// SetOutput sets the main command output writer. +func (r *RootCmd) SetOutput(w io.Writer) { + r.c.SetOut(w) + r.c.SetErr(w) +} + // Execute proxies the cobra.Command execution. func (r *RootCmd) Execute() error { return r.c.Execute() diff --git a/cmd/testdata/autohelp.txt b/cmd/testdata/autohelp.txt index b293deb7..8e789323 100644 --- a/cmd/testdata/autohelp.txt +++ b/cmd/testdata/autohelp.txt @@ -1,4 +1,5 @@ -level=INFO msg="specify a valid processor" processors="[docker kubernetes kubernetes-in-cluster local]" +INFO specify a valid processor + └ processors: [docker kubernetes kubernetes-in-cluster local] {{ .Desc }} {{ .Usage }} diff --git a/cmd/testdata/configs/1.yaml b/cmd/testdata/configs/1.yaml index 98cd8d76..0f2d41e0 100644 --- a/cmd/testdata/configs/1.yaml +++ b/cmd/testdata/configs/1.yaml @@ -3,4 +3,5 @@ kernelversion: 59 target: ubuntu-aws output: module: /tmp/falco-ubuntu-aws.ko + probe: /tmp/falco-ubuntu-aws.o driverversion: master diff --git a/cmd/testdata/configs/2.yaml b/cmd/testdata/configs/2.yaml index 9260a15a..ca6d01fc 100644 --- a/cmd/testdata/configs/2.yaml +++ b/cmd/testdata/configs/2.yaml @@ -7,4 +7,5 @@ kernelurls: [ target: ubuntu-aws output: module: /tmp/falco-ubuntu-aws.ko + probe: /tmp/falco-ubuntu-aws.o driverversion: master diff --git a/cmd/testdata/docker-from-config-debug.txt b/cmd/testdata/docker-from-config-debug.txt index 99544a34..17ed232c 100644 --- a/cmd/testdata/docker-from-config-debug.txt +++ b/cmd/testdata/docker-from-config-debug.txt @@ -1,3 +1,13 @@ -level=INFO msg="using config file" file=testdata/configs/1.yaml -level=DEBUG msg="running with options" output-module=/tmp/falco-ubuntu-aws.ko output-probe="" driverversion=master kernelrelease=4.15.0-1057-aws kernelversion=59 target=ubuntu-aws arch={{ .CurrentArch }} kernelurls=[] repo-org=falcosecurity repo-name=libs -level=INFO msg="driver building, it will take a few seconds" processor=docker +INFO using config file file: testdata/configs/1.yaml +DEBUG running with options + ├ output-module: /tmp/falco-ubuntu-aws.ko + ├ output-probe: /tmp/falco-ubuntu-aws.o + ├ driverversion: master + ├ kernelrelease: 4.15.0-1057-aws + ├ kernelversion: 59 + ├ target: ubuntu-aws + ├ arch: {{ .CurrentArch }} + ├ kernelurls: [] + ├ repo-org: falcosecurity + └ repo-name: libs +INFO starting build processor: docker diff --git a/cmd/testdata/docker-override-from-config-debug.txt b/cmd/testdata/docker-override-from-config-debug.txt index dcce457b..8f4d5bfa 100644 --- a/cmd/testdata/docker-override-from-config-debug.txt +++ b/cmd/testdata/docker-override-from-config-debug.txt @@ -1,3 +1,13 @@ -level=INFO msg="using config file" file=testdata/configs/1.yaml -level=DEBUG msg="running with options" output-module=/tmp/override.ko output-probe="" driverversion=master kernelrelease=4.15.0-1057-aws kernelversion=229 target=ubuntu-aws arch={{ .CurrentArch }} kernelurls=[] repo-org=falcosecurity repo-name=libs -level=INFO msg="driver building, it will take a few seconds" processor=docker +INFO using config file file: testdata/configs/1.yaml +DEBUG running with options + ├ output-module: /tmp/override.ko + ├ output-probe: /tmp/falco-ubuntu-aws.o + ├ driverversion: master + ├ kernelrelease: 4.15.0-1057-aws + ├ kernelversion: 229 + ├ target: ubuntu-aws + ├ arch: {{ .CurrentArch }} + ├ kernelurls: [] + ├ repo-org: falcosecurity + └ repo-name: libs +INFO starting build processor: docker diff --git a/cmd/testdata/docker-override-urls-from-config-debug.txt b/cmd/testdata/docker-override-urls-from-config-debug.txt index 39dbee47..a97c8abd 100644 --- a/cmd/testdata/docker-override-urls-from-config-debug.txt +++ b/cmd/testdata/docker-override-urls-from-config-debug.txt @@ -1,3 +1,13 @@ -level=INFO msg="using config file" file=testdata/configs/2.yaml -level=DEBUG msg="running with options" output-module=/tmp/falco-ubuntu-aws.ko output-probe="" driverversion=master kernelrelease=4.15.0-1057-aws kernelversion=59 target=ubuntu-aws arch={{ .CurrentArch }} kernelurls="[https://mirrors.edge.kernel.org/ubuntu/pool/main/l/linux-aws/linux-aws-headers-4.15.0-1057_4.15.0-1057.59_all.deb https://mirrors.edge.kernel.org/ubuntu/pool/main/l/linux-aws/linux-headers-4.15.0-1057-aws_4.15.0-1057.59_amd64.deb]" repo-org=falcosecurity repo-name=libs -level=INFO msg="driver building, it will take a few seconds" processor=docker +INFO using config file file: testdata/configs/2.yaml +DEBUG running with options + ├ output-module: /tmp/falco-ubuntu-aws.ko + ├ output-probe: /tmp/falco-ubuntu-aws.o + ├ driverversion: master + ├ kernelrelease: 4.15.0-1057-aws + ├ kernelversion: 59 + ├ target: ubuntu-aws + ├ arch: {{ .CurrentArch }} + ├ kernelurls: [https://mirrors.edge.kernel.org/ubuntu/pool/main/l/linux-aws/linux-aws-headers-4.15.0-1057_4.15.0-1057.59_all.deb https://mirrors.edge.kernel.org/ubuntu/pool/main/l/linux-aws/linux-headers-4.15.0-1057-aws_4.15.0-1057.59_amd64.deb] + ├ repo-org: falcosecurity + └ repo-name: libs +INFO starting build processor: docker diff --git a/cmd/testdata/docker-related-target-debug.txt b/cmd/testdata/docker-related-target-debug.txt index 56ca2299..3d3212dc 100644 --- a/cmd/testdata/docker-related-target-debug.txt +++ b/cmd/testdata/docker-related-target-debug.txt @@ -1,3 +1,13 @@ -level=DEBUG msg="running without a configuration file" -level=DEBUG msg="running with options" output-module=/tmp/falco-ubuntu-azure.ko output-probe="" driverversion=master kernelrelease=4.15.0-1057-azure kernelversion=62 target=ubuntu-azure arch={{ .CurrentArch }} kernelurls="[http://mirrors.edge.kernel.org/ubuntu/pool/main/l/linux-azure/linux-azure-headers-4.15.0-1057_4.15.0-1057.62_all.deb http://mirrors.edge.kernel.org/ubuntu/pool/main/l/linux-azure/linux-headers-4.15.0-1057-azure_4.15.0-1057.62_amd64.deb]" repo-org=falcosecurity repo-name=libs -level=INFO msg="driver building, it will take a few seconds" processor=docker +DEBUG running without a configuration file +DEBUG running with options + ├ output-module: /tmp/falco-ubuntu-azure.ko + ├ output-probe: /tmp/falco-ubuntu-aws.o + ├ driverversion: master + ├ kernelrelease: 4.15.0-1057-azure + ├ kernelversion: 62 + ├ target: ubuntu-azure + ├ arch: {{ .CurrentArch }} + ├ kernelurls: [http://mirrors.edge.kernel.org/ubuntu/pool/main/l/linux-azure/linux-azure-headers-4.15.0-1057_4.15.0-1057.62_all.deb http://mirrors.edge.kernel.org/ubuntu/pool/main/l/linux-azure/linux-headers-4.15.0-1057-azure_4.15.0-1057.62_amd64.deb] + ├ repo-org: falcosecurity + └ repo-name: libs +INFO starting build processor: docker diff --git a/cmd/testdata/docker-target-redhat-validation-error-debug.txt b/cmd/testdata/docker-target-redhat-validation-error-debug.txt index 1fe781ef..821eab1f 100644 --- a/cmd/testdata/docker-target-redhat-validation-error-debug.txt +++ b/cmd/testdata/docker-target-redhat-validation-error-debug.txt @@ -1,8 +1,4 @@ -level=DEBUG msg="running without a configuration file" -level=ERROR msg="error validating build options" err="builder image is a required field when target is redhat" -Error: exiting for validation errors -Usage: - driverkit docker [flags] - -{{ .Flags }} - +DEBUG running without a configuration file +ERROR error validating build options + └ err: builder image is a required field when target is redhat +ERROR error executing driverkit err: exiting for validation errors diff --git a/cmd/testdata/docker-with-flags-debug.txt b/cmd/testdata/docker-with-flags-debug.txt index ede541bc..cd954024 100644 --- a/cmd/testdata/docker-with-flags-debug.txt +++ b/cmd/testdata/docker-with-flags-debug.txt @@ -1,3 +1,13 @@ -level=DEBUG msg="running without a configuration file" -level=DEBUG msg="running with options" output-module=/tmp/falco-ubuntu-aws.ko output-probe="" driverversion=master kernelrelease=4.15.0-1057-aws kernelversion=59 target=ubuntu-aws arch={{ .CurrentArch }} kernelurls="[https://mirrors.edge.kernel.org/ubuntu/pool/main/l/linux-aws/linux-aws-headers-4.15.0-1057_4.15.0-1057.59_all.deb https://mirrors.edge.kernel.org/ubuntu/pool/main/l/linux-aws/linux-headers-4.15.0-1057-aws_4.15.0-1057.59_amd64.deb]" repo-org=falcosecurity repo-name=libs -level=INFO msg="driver building, it will take a few seconds" processor=docker +DEBUG running without a configuration file +DEBUG running with options + ├ output-module: /tmp/falco-ubuntu-aws.ko + ├ output-probe: /tmp/falco-ubuntu-aws.o + ├ driverversion: master + ├ kernelrelease: 4.15.0-1057-aws + ├ kernelversion: 59 + ├ target: ubuntu-aws + ├ arch: {{ .CurrentArch }} + ├ kernelurls: [https://mirrors.edge.kernel.org/ubuntu/pool/main/l/linux-aws/linux-aws-headers-4.15.0-1057_4.15.0-1057.59_all.deb https://mirrors.edge.kernel.org/ubuntu/pool/main/l/linux-aws/linux-headers-4.15.0-1057-aws_4.15.0-1057.59_amd64.deb] + ├ repo-org: falcosecurity + └ repo-name: libs +INFO starting build processor: docker diff --git a/cmd/testdata/docker-with-flags.txt b/cmd/testdata/docker-with-flags.txt index 3922ce6f..163b4d2c 100644 --- a/cmd/testdata/docker-with-flags.txt +++ b/cmd/testdata/docker-with-flags.txt @@ -1 +1 @@ -level=INFO msg="driver building, it will take a few seconds" processor=docker +INFO starting build processor: docker diff --git a/cmd/testdata/dockernoopts.txt b/cmd/testdata/dockernoopts.txt index 942e7cbb..763f754f 100644 --- a/cmd/testdata/dockernoopts.txt +++ b/cmd/testdata/dockernoopts.txt @@ -1,10 +1,7 @@ -level=ERROR msg="error validating build options" err="kernel release is a required field" -level=ERROR msg="error validating build options" err="target is a required field" -level=ERROR msg="error validating build options" err="output module path is required when probe is missing" -level=ERROR msg="error validating build options" err="output probe path is required when module is missing" -Error: exiting for validation errors -Usage: - driverkit docker [flags] - -{{ .Flags }} - +ERROR error validating build options err: kernel release is a required field +ERROR error validating build options err: target is a required field +ERROR error validating build options + └ err: output module path is required when probe is missing +ERROR error validating build options + └ err: output probe path is required when module is missing +ERROR error executing driverkit err: exiting for validation errors diff --git a/cmd/testdata/invalid-proxyconfig.txt b/cmd/testdata/invalid-proxyconfig.txt index e5df89df..8e7393ca 100644 --- a/cmd/testdata/invalid-proxyconfig.txt +++ b/cmd/testdata/invalid-proxyconfig.txt @@ -1,11 +1,3 @@ -level=ERROR msg="error validating config options" err="proxy url must start with http:// or https:// or socks5:// prefix" -Error: exiting for validation errors -{{ .Usage }} - -{{ .Commands }} - -{{ .Flags }} - -v, --version version for driverkit - -{{ .Info }} - +ERROR error validating config options + └ err: proxy url must start with http:// or https:// or socks5:// prefix +ERROR error executing driverkit err: exiting for validation errors diff --git a/cmd/testdata/non-existent-processor.txt b/cmd/testdata/non-existent-processor.txt index 2a983321..8de2681a 100644 --- a/cmd/testdata/non-existent-processor.txt +++ b/cmd/testdata/non-existent-processor.txt @@ -1,10 +1 @@ -Error: invalid argument "abc" for "driverkit" -{{ .Usage }} - -{{ .Commands }} - -{{ .Flags }} - -v, --version version for driverkit - -{{ .Info }} - +ERROR error executing driverkit err: invalid argument "abc" for "driverkit" diff --git a/cmd/testdata/templates/flags.txt b/cmd/testdata/templates/flags.txt index fde8aa7b..2129531c 100644 --- a/cmd/testdata/templates/flags.txt +++ b/cmd/testdata/templates/flags.txt @@ -11,7 +11,7 @@ Flags: --kernelrelease string kernel release to build the module for, it can be found by executing 'uname -v' --kernelurls strings list of kernel header urls (e.g. --kernelurls --kernelurls --kernelurls ",") --kernelversion string kernel version to build the module for, it's the numeric value after the hash when you execute 'uname -v' (default "1") - -l, --loglevel string log level (default "INFO") + -l, --loglevel string set level for logs (info, warn, debug, trace) (default "info") --moduledevicename string kernel module device name (the default is falco, so the device will be under /dev/falco*) (default "falco") --moduledrivername string kernel module driver name, i.e. the name you see when you check installed modules via lsmod (default "falco") --output-module string filepath where to save the resulting kernel module diff --git a/docs/driverkit.md b/docs/driverkit.md index 5f8d02d1..9611c354 100644 --- a/docs/driverkit.md +++ b/docs/driverkit.md @@ -21,7 +21,7 @@ driverkit --kernelrelease string kernel release to build the module for, it can be found by executing 'uname -v' --kernelurls strings list of kernel header urls (e.g. --kernelurls --kernelurls --kernelurls ",") --kernelversion string kernel version to build the module for, it's the numeric value after the hash when you execute 'uname -v' (default "1") - -l, --loglevel string Set level for logs (info, warn, debug, trace) (default "info") + -l, --loglevel string set level for logs (info, warn, debug, trace) (default "info") --moduledevicename string kernel module device name (the default is falco, so the device will be under /dev/falco*) (default "falco") --moduledrivername string kernel module driver name, i.e. the name you see when you check installed modules via lsmod (default "falco") --output-module string filepath where to save the resulting kernel module diff --git a/docs/driverkit_docker.md b/docs/driverkit_docker.md index 44265719..f500e257 100644 --- a/docs/driverkit_docker.md +++ b/docs/driverkit_docker.md @@ -21,7 +21,7 @@ driverkit docker [flags] --kernelrelease string kernel release to build the module for, it can be found by executing 'uname -v' --kernelurls strings list of kernel header urls (e.g. --kernelurls --kernelurls --kernelurls ",") --kernelversion string kernel version to build the module for, it's the numeric value after the hash when you execute 'uname -v' (default "1") - -l, --loglevel string Set level for logs (info, warn, debug, trace) (default "info") + -l, --loglevel string set level for logs (info, warn, debug, trace) (default "info") --moduledevicename string kernel module device name (the default is falco, so the device will be under /dev/falco*) (default "falco") --moduledrivername string kernel module driver name, i.e. the name you see when you check installed modules via lsmod (default "falco") --output-module string filepath where to save the resulting kernel module diff --git a/docs/driverkit_images.md b/docs/driverkit_images.md index dd33663d..541de565 100644 --- a/docs/driverkit_images.md +++ b/docs/driverkit_images.md @@ -21,7 +21,7 @@ driverkit images [flags] --kernelrelease string kernel release to build the module for, it can be found by executing 'uname -v' --kernelurls strings list of kernel header urls (e.g. --kernelurls --kernelurls --kernelurls ",") --kernelversion string kernel version to build the module for, it's the numeric value after the hash when you execute 'uname -v' (default "1") - -l, --loglevel string Set level for logs (info, warn, debug, trace) (default "info") + -l, --loglevel string set level for logs (info, warn, debug, trace) (default "info") --moduledevicename string kernel module device name (the default is falco, so the device will be under /dev/falco*) (default "falco") --moduledrivername string kernel module driver name, i.e. the name you see when you check installed modules via lsmod (default "falco") --output-module string filepath where to save the resulting kernel module diff --git a/docs/driverkit_kubernetes-in-cluster.md b/docs/driverkit_kubernetes-in-cluster.md index b756aec8..5a95597a 100644 --- a/docs/driverkit_kubernetes-in-cluster.md +++ b/docs/driverkit_kubernetes-in-cluster.md @@ -22,7 +22,7 @@ driverkit kubernetes-in-cluster [flags] --kernelrelease string kernel release to build the module for, it can be found by executing 'uname -v' --kernelurls strings list of kernel header urls (e.g. --kernelurls --kernelurls --kernelurls ",") --kernelversion string kernel version to build the module for, it's the numeric value after the hash when you execute 'uname -v' (default "1") - -l, --loglevel string Set level for logs (info, warn, debug, trace) (default "info") + -l, --loglevel string set level for logs (info, warn, debug, trace) (default "info") --moduledevicename string kernel module device name (the default is falco, so the device will be under /dev/falco*) (default "falco") --moduledrivername string kernel module driver name, i.e. the name you see when you check installed modules via lsmod (default "falco") -n, --namespace string If present, the namespace scope for the pods and its config (default "default") diff --git a/docs/driverkit_kubernetes.md b/docs/driverkit_kubernetes.md index edb294db..5cb28798 100644 --- a/docs/driverkit_kubernetes.md +++ b/docs/driverkit_kubernetes.md @@ -34,7 +34,7 @@ driverkit kubernetes [flags] --kernelurls strings list of kernel header urls (e.g. --kernelurls --kernelurls --kernelurls ",") --kernelversion string kernel version to build the module for, it's the numeric value after the hash when you execute 'uname -v' (default "1") --kubeconfig string path to the kubeconfig file to use for CLI requests - -l, --loglevel string Set level for logs (info, warn, debug, trace) (default "info") + -l, --loglevel string set level for logs (info, warn, debug, trace) (default "info") --moduledevicename string kernel module device name (the default is falco, so the device will be under /dev/falco*) (default "falco") --moduledrivername string kernel module driver name, i.e. the name you see when you check installed modules via lsmod (default "falco") -n, --namespace string If present, the namespace scope for the pods and its config (default "default") diff --git a/docs/driverkit_local.md b/docs/driverkit_local.md index 56caf140..d7a1bf10 100644 --- a/docs/driverkit_local.md +++ b/docs/driverkit_local.md @@ -18,7 +18,7 @@ driverkit local [flags] -h, --help help for local --kernelrelease string kernel release to build the module for, it can be found by executing 'uname -v' --kernelversion string kernel version to build the module for, it's the numeric value after the hash when you execute 'uname -v' (default "1") - -l, --loglevel string Set level for logs (info, warn, debug, trace) (default "info") + -l, --loglevel string set level for logs (info, warn, debug, trace) (default "info") --moduledevicename string kernel module device name (the default is falco, so the device will be under /dev/falco*) (default "falco") --moduledrivername string kernel module driver name, i.e. the name you see when you check installed modules via lsmod (default "falco") --output-module string filepath where to save the resulting kernel module From 66e37f7928fd6c4ca1808e87841ff7f93865b2d1 Mon Sep 17 00:00:00 2001 From: Federico Di Pierro Date: Tue, 23 Apr 2024 11:00:33 +0200 Subject: [PATCH 5/5] chore(go.sum): bumped docker library. Signed-off-by: Federico Di Pierro --- go.sum | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/go.sum b/go.sum index 65c42edc..0243ae55 100644 --- a/go.sum +++ b/go.sum @@ -71,8 +71,8 @@ github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5Qvfr github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= github.com/docker/cli v24.0.7+incompatible h1:wa/nIwYFW7BVTGa7SWPVyyXU9lgORqUb1xfI36MSkFg= github.com/docker/cli v24.0.7+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= -github.com/docker/docker v26.0.0+incompatible h1:Ng2qi+gdKADUa/VM+6b6YaY2nlZhk/lVJiKR/2bMudU= -github.com/docker/docker v26.0.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v26.0.2+incompatible h1:yGVmKUFGgcxA6PXWAokO0sQL22BrQ67cgVjko8tGdXE= +github.com/docker/docker v26.0.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker-credential-helpers v0.8.0 h1:YQFtbBQb4VrpoPxhFuzEBPQ9E16qz5SpHLS+uswaCp8= github.com/docker/docker-credential-helpers v0.8.0/go.mod h1:UGFXcuoQ5TxPiB54nHOZ32AWRqQdECoh/Mg0AlEYb40= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= @@ -406,15 +406,10 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -<<<<<<< HEAD +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= -======= -golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc= -golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= ->>>>>>> 9723857 (new(cmd,pkg,docs,docgen,validate): switched from `slog` go library to use rich-text falcoctl log library.) golang.org/x/oauth2 v0.18.0 h1:09qnuIAgzdx1XplqJvW6CQqMCtGZykZWcXzPMPUusvI= golang.org/x/oauth2 v0.18.0/go.mod h1:Wf7knwG0MPoWIMMBgFlEaSUDaKskp0dCfrlJRJXbBi8= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=