feat: respect custom exit code from plugin (#6584)

Signed-off-by: knqyf263 <knqyf263@gmail.com>
This commit is contained in:
Teppei Fukuda
2024-05-02 09:07:49 +04:00
committed by GitHub
parent a5d485cf8a
commit f0961d54f6
10 changed files with 41 additions and 24 deletions

View File

@@ -2,6 +2,7 @@ package main
import (
"context"
"errors"
"os"
"golang.org/x/xerrors"
@@ -9,12 +10,17 @@ import (
"github.com/aquasecurity/trivy/pkg/commands"
"github.com/aquasecurity/trivy/pkg/log"
"github.com/aquasecurity/trivy/pkg/plugin"
"github.com/aquasecurity/trivy/pkg/types"
_ "modernc.org/sqlite" // sqlite driver for RPM DB and Java DB
)
func main() {
if err := run(); err != nil {
var exitError *types.ExitError
if errors.As(err, &exitError) {
os.Exit(exitError.Code)
}
log.Fatal("Fatal error", log.Err(err))
}
}

View File

@@ -18,6 +18,7 @@ import (
"github.com/aquasecurity/trivy/pkg/commands/operation"
"github.com/aquasecurity/trivy/pkg/flag"
"github.com/aquasecurity/trivy/pkg/log"
"github.com/aquasecurity/trivy/pkg/types"
)
var allSupportedServicesFunc = awsScanner.AllSupportedServices
@@ -170,6 +171,5 @@ func Run(ctx context.Context, opt flag.Options) error {
return xerrors.Errorf("unable to write results: %w", err)
}
operation.Exit(opt, r.Failed())
return nil
return operation.Exit(opt, r.Failed(), types.Metadata{})
}

View File

@@ -130,6 +130,8 @@ func loadPluginCommands() []*cobra.Command {
return nil
},
DisableFlagParsing: true,
SilenceUsage: true,
SilenceErrors: true,
}
commands = append(commands, cmd)
}

View File

@@ -452,10 +452,7 @@ func Run(ctx context.Context, opts flag.Options, targetKind TargetKind) (err err
return xerrors.Errorf("report error: %w", err)
}
operation.ExitOnEOL(opts, report.Metadata)
operation.Exit(opts, report.Results.Failed())
return nil
return operation.Exit(opts, report.Results.Failed(), report.Metadata)
}
func disabledAnalyzers(opts flag.Options) []analyzer.Type {

View File

@@ -44,8 +44,5 @@ func Run(ctx context.Context, opts flag.Options) (err error) {
return xerrors.Errorf("unable to write results: %w", err)
}
operation.ExitOnEOL(opts, r.Metadata)
operation.Exit(opts, r.Results.Failed())
return nil
return operation.Exit(opts, r.Results.Failed(), r.Metadata)
}

View File

@@ -204,16 +204,15 @@ func GetTLSConfig(caCertPath, certPath, keyPath string) (*x509.CertPool, tls.Cer
return caCertPool, cert, nil
}
func Exit(opts flag.Options, failedResults bool) {
if opts.ExitCode != 0 && failedResults {
os.Exit(opts.ExitCode)
}
}
func ExitOnEOL(opts flag.Options, m types.Metadata) {
func Exit(opts flag.Options, failedResults bool, m types.Metadata) error {
if opts.ExitOnEOL != 0 && m.OS != nil && m.OS.Eosl {
log.Error("Detected EOL OS", log.String("family", string(m.OS.Family)),
log.String("version", m.OS.Name))
os.Exit(opts.ExitOnEOL)
return &types.ExitError{Code: opts.ExitOnEOL}
}
if opts.ExitCode != 0 && failedResults {
return &types.ExitError{Code: opts.ExitCode}
}
return nil
}

View File

@@ -122,9 +122,7 @@ func (r *runner) run(ctx context.Context, artifacts []*k8sArtifacts.Artifact) er
return xerrors.Errorf("unable to write results: %w", err)
}
operation.Exit(r.flagOpts, rpt.Failed())
return nil
return operation.Exit(r.flagOpts, rpt.Failed(), types.Metadata{})
}
// Full-cluster scanning with '--format table' without explicit '--report all' is not allowed so that it won't mess up user's terminal.

View File

@@ -2,6 +2,7 @@ package plugin
import (
"context"
"errors"
"fmt"
"io"
"os"
@@ -15,6 +16,7 @@ import (
"github.com/aquasecurity/trivy/pkg/downloader"
"github.com/aquasecurity/trivy/pkg/log"
"github.com/aquasecurity/trivy/pkg/types"
"github.com/aquasecurity/trivy/pkg/utils/fsutils"
)
@@ -111,8 +113,11 @@ func (p Plugin) Run(ctx context.Context, opts RunOptions) error {
// out if the error was from not being able to execute the plugin or
// an error set by the plugin itself.
if err = cmd.Run(); err != nil {
if _, ok := err.(*exec.ExitError); !ok {
return xerrors.Errorf("exit: %w", err)
var execError *exec.ExitError
if errors.As(err, &execError) {
return &types.ExitError{
Code: execError.ExitCode(),
}
}
return xerrors.Errorf("plugin exec: %w", err)
}

View File

@@ -140,7 +140,7 @@ func TestPlugin_Run(t *testing.T) {
GOOS: "linux",
GOARCH: "amd64",
},
wantErr: "plugin exec: exit status 1",
wantErr: "exit status 1",
},
}
for _, tt := range tests {

13
pkg/types/error.go Normal file
View File

@@ -0,0 +1,13 @@
package types
import (
"fmt"
)
type ExitError struct {
Code int
}
func (e *ExitError) Error() string {
return fmt.Sprintf("exit status %d", e.Code)
}