Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 3 additions & 6 deletions cmd/artifact/install/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import (
"path/filepath"
"runtime"

"github.com/pterm/pterm"
"github.com/spf13/cobra"
"github.com/spf13/viper"

Expand Down Expand Up @@ -182,8 +181,6 @@ Examples:

// RunArtifactInstall executes the business logic for the artifact install command.
func (o *artifactInstallOptions) RunArtifactInstall(ctx context.Context, args []string) error {
var sp *pterm.SpinnerPrinter

logger := o.Printer.Logger
// Retrieve configuration for installer
configuredInstaller, err := config.Installer()
Expand Down Expand Up @@ -317,7 +314,7 @@ func (o *artifactInstallOptions) RunArtifactInstall(ctx context.Context, args []
logger.Info("Extracting and installing artifact", logger.Args("type", result.Type, "file", result.Filename))

if !o.Printer.DisableStyling {
sp, _ = o.Printer.Spinner.Start("Extracting and installing")
o.Printer.Spinner, _ = o.Printer.Spinner.Start("Extracting and installing")
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to save the spinner to our o.Printer one to let main properly stop the right spinner when a context error happens.

}

result.Filename = filepath.Join(tmpDir, result.Filename)
Expand All @@ -337,8 +334,8 @@ func (o *artifactInstallOptions) RunArtifactInstall(ctx context.Context, args []
return err
}

if sp != nil {
_ = sp.Stop()
if o.Printer.Spinner != nil {
_ = o.Printer.Spinner.Stop()
}
logger.Info("Artifact successfully installed", logger.Args("name", ref, "type", result.Type, "digest", result.Digest, "directory", destDir))
}
Expand Down
22 changes: 21 additions & 1 deletion cmd/driver/cleanup/cleanup.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@
package drivercleanup

import (
"bytes"
"strings"

"github.com/pterm/pterm"
"github.com/spf13/cobra"
"golang.org/x/net/context"

Expand Down Expand Up @@ -51,5 +55,21 @@ func (o *driverCleanupOptions) RunDriverCleanup(_ context.Context) error {
o.Printer.Logger.Info("Running falcoctl driver cleanup", o.Printer.Logger.Args(
"driver type", o.Driver.Type,
"driver name", o.Driver.Name))
return o.Driver.Type.Cleanup(o.Printer, o.Driver.Name)
var buf bytes.Buffer
if !o.Printer.DisableStyling {
o.Printer.Spinner, _ = o.Printer.Spinner.Start("Cleaning up existing drivers")
}
err := o.Driver.Type.Cleanup(o.Printer.WithWriter(&buf), o.Driver.Name)
if o.Printer.Spinner != nil {
_ = o.Printer.Spinner.Stop()
}
if o.Printer.Logger.Formatter == pterm.LogFormatterJSON {
// Only print formatted text if we are formatting to json
out := strings.ReplaceAll(buf.String(), "\n", ";")
o.Printer.Logger.Info("Driver build", o.Printer.Logger.Args("output", out))
} else {
// Print much more readable output as-is
o.Printer.DefaultText.Print(buf.String())
}
return err
}
2 changes: 1 addition & 1 deletion cmd/driver/driver_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ func NewDriverCmd(ctx context.Context, opt *options.Common) *cobra.Command {
}
}

if driverTypes.String() != "auto" {
if driverTypes.String() != drivertype.TypeAuto {
var err error
// Ok driver type was enforced by the user
driver.Type, err = drivertype.Parse(driverTypes.String())
Expand Down
77 changes: 69 additions & 8 deletions cmd/driver/install/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,15 @@
package driverinstall

import (
"bytes"
"crypto/tls"
"errors"
"fmt"
"net/http"
"strings"
"time"

"github.com/pterm/pterm"
"github.com/spf13/cobra"
"golang.org/x/net/context"

Expand Down Expand Up @@ -140,30 +143,88 @@ func (o *driverInstallOptions) RunDriverInstall(ctx context.Context) (string, er
}
o.Printer.Logger.Info("found distro", o.Printer.Logger.Args("target", d))

err = o.Driver.Type.Cleanup(o.Printer, o.Driver.Name)
var (
dest string
buf bytes.Buffer
)

if !o.Printer.DisableStyling {
o.Printer.Spinner, _ = o.Printer.Spinner.Start("Cleaning up existing drivers")
}
err = o.Driver.Type.Cleanup(o.Printer.WithWriter(&buf), o.Driver.Name)
if o.Printer.Spinner != nil {
_ = o.Printer.Spinner.Stop()
}
if o.Printer.Logger.Formatter == pterm.LogFormatterJSON {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is ugly: we should probably find a better way to deal with unformatted logs while in JSON mode.

// Only print formatted text if we are formatting to json
out := strings.ReplaceAll(buf.String(), "\n", ";")
o.Printer.Logger.Info("Driver build", o.Printer.Logger.Args("output", out))
} else {
// Print much more readable output as-is
o.Printer.DefaultText.Print(buf.String())
}
if err != nil {
return "", err
}

setDefaultHTTPClientOpts(o.driverDownloadOptions)

var dest string
if o.Download {
dest, err = driverdistro.Download(ctx, d, o.Printer, kr, o.Driver.Name, o.Driver.Type, o.Driver.Version, o.Driver.Repos)
setDefaultHTTPClientOpts(o.driverDownloadOptions)
if !o.Printer.DisableStyling {
o.Printer.Spinner, _ = o.Printer.Spinner.Start("Trying to download the driver")
}
dest, err = driverdistro.Download(ctx, d, o.Printer.WithWriter(&buf), kr, o.Driver.Name, o.Driver.Type, o.Driver.Version, o.Driver.Repos)
if o.Printer.Spinner != nil {
_ = o.Printer.Spinner.Stop()
}
if o.Printer.Logger.Formatter == pterm.LogFormatterJSON {
// Only print formatted text if we are formatting to json
out := strings.ReplaceAll(buf.String(), "\n", ";")
o.Printer.Logger.Info("Driver build", o.Printer.Logger.Args("output", out))
} else {
// Print much more readable output as-is
o.Printer.DefaultText.Print(buf.String())
}
buf.Reset()
if err == nil {
o.Printer.Logger.Info("Driver downloaded.", o.Printer.Logger.Args("path", dest))
return dest, nil
}
if errors.Is(err, driverdistro.ErrAlreadyPresent) {
o.Printer.Logger.Info("Skipping download, driver already present.", o.Printer.Logger.Args("path", dest))
return dest, nil
}
// Print the error but go on
// attempting a build if requested
o.Printer.Logger.Warn(err.Error())
if o.Compile {
o.Printer.Logger.Warn(err.Error())
}
}

if o.Compile {
dest, err = driverdistro.Build(ctx, d, o.Printer, kr, o.Driver.Name, o.Driver.Type, o.Driver.Version)
if !o.Printer.DisableStyling {
o.Printer.Spinner, _ = o.Printer.Spinner.Start("Trying to build the driver")
}
dest, err = driverdistro.Build(ctx, d, o.Printer.WithWriter(&buf), kr, o.Driver.Name, o.Driver.Type, o.Driver.Version)
if o.Printer.Spinner != nil {
_ = o.Printer.Spinner.Stop()
}
if o.Printer.Logger.Formatter == pterm.LogFormatterJSON {
// Only print formatted text if we are formatting to json
out := strings.ReplaceAll(buf.String(), "\n", ";")
o.Printer.Logger.Info("Driver build", o.Printer.Logger.Args("output", out))
} else {
// Print much more readable output as-is
o.Printer.DefaultText.Print(buf.String())
}
buf.Reset()
if err == nil {
o.Printer.Logger.Info("Driver built.", o.Printer.Logger.Args("path", dest))
return dest, nil
}
if errors.Is(err, driverdistro.ErrAlreadyPresent) {
o.Printer.Logger.Info("Skipping build, driver already present.", o.Printer.Logger.Args("path", dest))
return dest, nil
}
o.Printer.Logger.Warn(err.Error())
}

return o.Driver.Name, fmt.Errorf("failed: %w", err)
Expand Down
3 changes: 3 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ func main() {
if opt.Printer != nil && opt.Printer.ProgressBar != nil && opt.Printer.ProgressBar.IsActive {
_, _ = opt.Printer.ProgressBar.Stop()
}
if opt.Printer != nil && opt.Printer.Spinner != nil && opt.Printer.Spinner.IsActive {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If there's a spinner in use, stop it upon leaving.

_ = opt.Printer.Spinner.Stop()
}
opt.Printer.Logger.Info("Received signal, terminating...")
stop()
}()
Expand Down
20 changes: 6 additions & 14 deletions pkg/driver/distro/distro.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ var (
hostRoot = string(os.PathSeparator)
// ErrUnsupported is the error returned when the target distro is not supported.
ErrUnsupported = errors.New("failed to determine distro")
// ErrAlreadyPresent is the error returned when a driver is already present on filesystem.
ErrAlreadyPresent = errors.New("driver already present")
)

// Distro is the common interface used by distro-specific implementations.
Expand Down Expand Up @@ -169,8 +171,7 @@ func Build(ctx context.Context,
driverFileName := toFilename(d, &kr, driverName, driverType)
destination := toLocalPath(driverVer, driverFileName, kr.Architecture.ToNonDeb())
if exist, _ := utils.FileExists(destination); exist {
printer.Logger.Info("Skipping build, driver already present.", printer.Logger.Args("path", destination))
return destination, nil
return destination, ErrAlreadyPresent
}

env, err := d.customizeBuild(ctx, printer, driverType, kr)
Expand All @@ -189,11 +190,7 @@ func Build(ctx context.Context,
if err != nil {
return "", err
}
err = copyDataToLocalPath(destination, f)
if err == nil {
printer.Logger.Info("Driver built.", printer.Logger.Args("path", destination))
}
return destination, err
return destination, copyDataToLocalPath(destination, f)
}

// Download will try to download drivers for a distro trying specified repos.
Expand All @@ -211,8 +208,7 @@ func Download(ctx context.Context,
// Skip if existent
destination := toLocalPath(driverVer, driverFileName, kr.Architecture.ToNonDeb())
if exist, _ := utils.FileExists(destination); exist {
printer.Logger.Info("Skipping download, driver already present.", printer.Logger.Args("path", destination))
return destination, nil
return destination, ErrAlreadyPresent
}

// Try to download from any specified repository,
Expand All @@ -236,11 +232,7 @@ func Download(ctx context.Context,
}
continue
}
err = copyDataToLocalPath(destination, resp.Body)
if err == nil {
printer.Logger.Info("Driver downloaded.", printer.Logger.Args("path", destination))
}
return destination, err
return destination, copyDataToLocalPath(destination, resp.Body)
}
return destination, fmt.Errorf("unable to find a prebuilt driver")
}
Expand Down
12 changes: 4 additions & 8 deletions pkg/driver/type/bpf.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,6 @@ func (b *bpf) Build(ctx context.Context,
driverName, driverVersion string,
env map[string]string,
) (string, error) {
printer.Logger.Info("Trying to compile the eBPF probe")

srcPath := fmt.Sprintf("/usr/src/%s-%s/bpf", driverName, driverVersion)

makeCmdArgs := fmt.Sprintf(`make -C %q`, filepath.Clean(srcPath))
Expand All @@ -88,12 +86,10 @@ func (b *bpf) Build(ctx context.Context,
for key, val := range env {
makeCmd.Env = append(makeCmd.Env, fmt.Sprintf("%s=%s", key, val))
}
err := runCmdPipingStdout(printer, makeCmd)
outProbe := fmt.Sprintf("%s/probe.o", srcPath)
if err == nil {
printer.Logger.Info("Probe successfully built.", printer.Logger.Args("file", outProbe))
} else {
printer.Logger.Info("Failed to build probe.", printer.Logger.Args("err", err))
out, err := makeCmd.CombinedOutput()
if err != nil {
printer.DefaultText.Print(string(out))
}
outProbe := fmt.Sprintf("%s/probe.o", srcPath)
return outProbe, err
}
6 changes: 2 additions & 4 deletions pkg/driver/type/kmod.go
Original file line number Diff line number Diff line change
Expand Up @@ -192,8 +192,6 @@ func (k *kmod) Build(ctx context.Context,
return "", fmt.Errorf("unsupported on uek hosts")
}

printer.Logger.Info("Trying to compile the kernel module")

out, err := exec.Command("which", "gcc").Output()
if err != nil {
return "", err
Expand Down Expand Up @@ -224,8 +222,7 @@ func (k *kmod) Build(ctx context.Context,
driverName, driverVersion, kr.String())

// Try the build through dkms
dkmsCmd := exec.CommandContext(ctx, "bash", "-c", dkmsCmdArgs) //nolint:gosec // false positive
err = runCmdPipingStdout(printer, dkmsCmd)
out, err = exec.CommandContext(ctx, "bash", "-c", dkmsCmdArgs).CombinedOutput() //nolint:gosec // false positive
if err == nil {
koGlob := fmt.Sprintf("/var/lib/dkms/%s/%s/%s/%s/module/%s", driverName, driverVersion, kr.String(), kr.Architecture.ToNonDeb(), driverName)
var koFiles []string
Expand All @@ -238,6 +235,7 @@ func (k *kmod) Build(ctx context.Context,
printer.Logger.Info("Module installed in dkms.", printer.Logger.Args("file", koFile))
return koFile, nil
}
printer.DefaultText.Print(string(out))
dkmsLogFile := fmt.Sprintf("/var/lib/dkms/$%s/%s/build/make.log", driverName, driverVersion)
logs, err := os.ReadFile(filepath.Clean(dkmsLogFile))
if err != nil {
Expand Down
30 changes: 4 additions & 26 deletions pkg/driver/type/type.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,17 @@
package drivertype

import (
"bufio"
"fmt"
"os/exec"

"github.com/falcosecurity/driverkit/pkg/kernelrelease"
"golang.org/x/net/context"

"github.com/falcosecurity/falcoctl/pkg/output"
)

// TypeAuto enables a smart automatic driver selection logic instead of using a fixed driver type.
const TypeAuto = "auto"

var driverTypes = map[string]DriverType{}

// DriverType is the interface that wraps driver types.
Expand All @@ -48,7 +49,7 @@ func GetTypes() []string {
}
// auto is a sentinel value to enable automatic driver selection logic,
// but it is not mapped to any DriverType
driverTypesSlice = append(driverTypesSlice, "auto")
driverTypesSlice = append(driverTypesSlice, TypeAuto)
return driverTypesSlice
}

Expand All @@ -59,26 +60,3 @@ func Parse(driverType string) (DriverType, error) {
}
return nil, fmt.Errorf("wrong driver type specified: %s", driverType)
}

func runCmdPipingStdout(printer *output.Printer, cmd *exec.Cmd) error {
stdout, err := cmd.StdoutPipe()
if err != nil {
printer.Logger.Warn("Failed to pipe output. Trying without piping.", printer.Logger.Args("err", err))
_, err = cmd.Output()
} else {
defer stdout.Close()
err = cmd.Start()
if err != nil {
printer.Logger.Warn("Failed to execute command.", printer.Logger.Args("err", err))
} else {
// print the output of the subprocess line by line
scanner := bufio.NewScanner(stdout)
for scanner.Scan() {
m := scanner.Text()
printer.DefaultText.Println(m)
}
err = cmd.Wait()
}
}
return err
}