mirror of
https://github.com/aquasecurity/trivy.git
synced 2025-12-12 07:40:48 -08:00
refactor(flag): improve flag system architecture and extensibility (#8718)
Co-authored-by: DmitriyLewen <91113035+DmitriyLewen@users.noreply.github.com>
This commit is contained in:
@@ -211,25 +211,26 @@ func NewRootCommand(globalFlags *flag.GlobalFlagGroup) *cobra.Command {
|
||||
return err
|
||||
}
|
||||
|
||||
globalOptions, err := globalFlags.ToOptions()
|
||||
flags := flag.Flags{globalFlags}
|
||||
opts, err := flags.ToOptions(args)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Initialize logger
|
||||
log.InitLogger(globalOptions.Debug, globalOptions.Quiet)
|
||||
log.InitLogger(opts.Debug, opts.Quiet)
|
||||
|
||||
return nil
|
||||
},
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
globalOptions, err := globalFlags.ToOptions()
|
||||
flags := flag.Flags{globalFlags}
|
||||
opts, err := flags.ToOptions(args)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if globalOptions.ShowVersion {
|
||||
if opts.ShowVersion {
|
||||
// Customize version output
|
||||
return showVersion(globalOptions.CacheDir, versionFormat, cmd.OutOrStdout())
|
||||
return showVersion(opts.CacheDir, versionFormat, cmd.OutOrStdout())
|
||||
} else {
|
||||
return cmd.Help()
|
||||
}
|
||||
@@ -255,27 +256,30 @@ func NewImageCommand(globalFlags *flag.GlobalFlagGroup) *cobra.Command {
|
||||
compliance.Values = []string{types.ComplianceDockerCIS160}
|
||||
reportFlagGroup.Compliance = compliance // override usage as the accepted values differ for each subcommand.
|
||||
|
||||
imageFlags := &flag.Flags{
|
||||
GlobalFlagGroup: globalFlags,
|
||||
CacheFlagGroup: flag.NewCacheFlagGroup(),
|
||||
DBFlagGroup: flag.NewDBFlagGroup(),
|
||||
ImageFlagGroup: flag.NewImageFlagGroup(), // container image specific
|
||||
LicenseFlagGroup: flag.NewLicenseFlagGroup(),
|
||||
MisconfFlagGroup: flag.NewMisconfFlagGroup(),
|
||||
ModuleFlagGroup: flag.NewModuleFlagGroup(),
|
||||
PackageFlagGroup: flag.NewPackageFlagGroup(),
|
||||
RemoteFlagGroup: flag.NewClientFlags(), // for client/server mode
|
||||
RegistryFlagGroup: flag.NewRegistryFlagGroup(),
|
||||
RegoFlagGroup: flag.NewRegoFlagGroup(),
|
||||
ReportFlagGroup: reportFlagGroup,
|
||||
ScanFlagGroup: flag.NewScanFlagGroup(),
|
||||
SecretFlagGroup: flag.NewSecretFlagGroup(),
|
||||
VulnerabilityFlagGroup: flag.NewVulnerabilityFlagGroup(),
|
||||
}
|
||||
packageFlagGroup := flag.NewPackageFlagGroup()
|
||||
packageFlagGroup.IncludeDevDeps = nil // disable '--include-dev-deps'
|
||||
|
||||
imageFlags.PackageFlagGroup.IncludeDevDeps = nil // disable '--include-dev-deps'
|
||||
imageFlags.MisconfFlagGroup.CloudformationParamVars = nil // disable '--cf-params'
|
||||
imageFlags.MisconfFlagGroup.TerraformTFVars = nil // disable '--tf-vars'
|
||||
misconfFlagGroup := flag.NewMisconfFlagGroup()
|
||||
misconfFlagGroup.CloudformationParamVars = nil // disable '--cf-params'
|
||||
misconfFlagGroup.TerraformTFVars = nil // disable '--tf-vars'
|
||||
|
||||
imageFlags := flag.Flags{
|
||||
globalFlags,
|
||||
flag.NewCacheFlagGroup(),
|
||||
flag.NewDBFlagGroup(),
|
||||
flag.NewImageFlagGroup(), // container image specific flags
|
||||
flag.NewLicenseFlagGroup(),
|
||||
misconfFlagGroup,
|
||||
flag.NewModuleFlagGroup(),
|
||||
packageFlagGroup,
|
||||
flag.NewClientFlags(),
|
||||
flag.NewRegistryFlagGroup(),
|
||||
flag.NewRegoFlagGroup(),
|
||||
reportFlagGroup,
|
||||
flag.NewScanFlagGroup(),
|
||||
flag.NewSecretFlagGroup(),
|
||||
flag.NewVulnerabilityFlagGroup(),
|
||||
}
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "image [flags] IMAGE_NAME",
|
||||
@@ -335,26 +339,29 @@ func NewImageCommand(globalFlags *flag.GlobalFlagGroup) *cobra.Command {
|
||||
}
|
||||
|
||||
func NewFilesystemCommand(globalFlags *flag.GlobalFlagGroup) *cobra.Command {
|
||||
fsFlags := &flag.Flags{
|
||||
GlobalFlagGroup: globalFlags,
|
||||
CacheFlagGroup: flag.NewCacheFlagGroup(),
|
||||
DBFlagGroup: flag.NewDBFlagGroup(),
|
||||
LicenseFlagGroup: flag.NewLicenseFlagGroup(),
|
||||
MisconfFlagGroup: flag.NewMisconfFlagGroup(),
|
||||
ModuleFlagGroup: flag.NewModuleFlagGroup(),
|
||||
PackageFlagGroup: flag.NewPackageFlagGroup(),
|
||||
RemoteFlagGroup: flag.NewClientFlags(), // for client/server mode
|
||||
RegistryFlagGroup: flag.NewRegistryFlagGroup(),
|
||||
RegoFlagGroup: flag.NewRegoFlagGroup(),
|
||||
ReportFlagGroup: flag.NewReportFlagGroup(),
|
||||
ScanFlagGroup: flag.NewScanFlagGroup(),
|
||||
SecretFlagGroup: flag.NewSecretFlagGroup(),
|
||||
VulnerabilityFlagGroup: flag.NewVulnerabilityFlagGroup(),
|
||||
}
|
||||
cacheFlagGroup := flag.NewCacheFlagGroup()
|
||||
cacheFlagGroup.CacheBackend.Default = string(cache.TypeMemory) // Use memory cache by default
|
||||
|
||||
fsFlags.CacheFlagGroup.CacheBackend.Default = string(cache.TypeMemory) // Use memory cache by default
|
||||
fsFlags.ReportFlagGroup.ReportFormat.Usage = "specify a compliance report format for the output" // @TODO: support --report summary for non compliance reports
|
||||
fsFlags.ReportFlagGroup.ExitOnEOL = nil // disable '--exit-on-eol'
|
||||
reportFlagGroup := flag.NewReportFlagGroup()
|
||||
reportFlagGroup.ReportFormat.Usage = "specify a compliance report format for the output" // @TODO: support --report summary for non compliance reports
|
||||
reportFlagGroup.ExitOnEOL = nil // disable '--exit-on-eol'
|
||||
|
||||
fsFlags := flag.Flags{
|
||||
globalFlags,
|
||||
cacheFlagGroup,
|
||||
flag.NewDBFlagGroup(),
|
||||
flag.NewLicenseFlagGroup(),
|
||||
flag.NewMisconfFlagGroup(),
|
||||
flag.NewModuleFlagGroup(),
|
||||
flag.NewPackageFlagGroup(),
|
||||
flag.NewClientFlags(), // for client/server mode
|
||||
flag.NewRegistryFlagGroup(),
|
||||
flag.NewRegoFlagGroup(),
|
||||
reportFlagGroup,
|
||||
flag.NewScanFlagGroup(),
|
||||
flag.NewSecretFlagGroup(),
|
||||
flag.NewVulnerabilityFlagGroup(),
|
||||
}
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "filesystem [flags] PATH",
|
||||
@@ -394,27 +401,33 @@ func NewFilesystemCommand(globalFlags *flag.GlobalFlagGroup) *cobra.Command {
|
||||
}
|
||||
|
||||
func NewRootfsCommand(globalFlags *flag.GlobalFlagGroup) *cobra.Command {
|
||||
rootfsFlags := &flag.Flags{
|
||||
GlobalFlagGroup: globalFlags,
|
||||
CacheFlagGroup: flag.NewCacheFlagGroup(),
|
||||
DBFlagGroup: flag.NewDBFlagGroup(),
|
||||
LicenseFlagGroup: flag.NewLicenseFlagGroup(),
|
||||
MisconfFlagGroup: flag.NewMisconfFlagGroup(),
|
||||
ModuleFlagGroup: flag.NewModuleFlagGroup(),
|
||||
PackageFlagGroup: flag.NewPackageFlagGroup(),
|
||||
RemoteFlagGroup: flag.NewClientFlags(), // for client/server mode
|
||||
RegistryFlagGroup: flag.NewRegistryFlagGroup(),
|
||||
RegoFlagGroup: flag.NewRegoFlagGroup(),
|
||||
ReportFlagGroup: flag.NewReportFlagGroup(),
|
||||
ScanFlagGroup: flag.NewScanFlagGroup(),
|
||||
SecretFlagGroup: flag.NewSecretFlagGroup(),
|
||||
VulnerabilityFlagGroup: flag.NewVulnerabilityFlagGroup(),
|
||||
reportFlagGroup := flag.NewReportFlagGroup()
|
||||
reportFlagGroup.ReportFormat = nil // TODO: support --report summary
|
||||
reportFlagGroup.Compliance = nil // disable '--compliance'
|
||||
reportFlagGroup.ReportFormat = nil // disable '--report'
|
||||
|
||||
packageFlagGroup := flag.NewPackageFlagGroup()
|
||||
packageFlagGroup.IncludeDevDeps = nil // disable '--include-dev-deps'
|
||||
|
||||
cacheFlagGroup := flag.NewCacheFlagGroup()
|
||||
cacheFlagGroup.CacheBackend.Default = string(cache.TypeMemory) // Use memory cache by default
|
||||
|
||||
rootfsFlags := flag.Flags{
|
||||
globalFlags,
|
||||
cacheFlagGroup,
|
||||
flag.NewDBFlagGroup(),
|
||||
flag.NewLicenseFlagGroup(),
|
||||
flag.NewMisconfFlagGroup(),
|
||||
flag.NewModuleFlagGroup(),
|
||||
packageFlagGroup,
|
||||
flag.NewClientFlags(), // for client/server mode
|
||||
flag.NewRegistryFlagGroup(),
|
||||
flag.NewRegoFlagGroup(),
|
||||
reportFlagGroup,
|
||||
flag.NewScanFlagGroup(),
|
||||
flag.NewSecretFlagGroup(),
|
||||
flag.NewVulnerabilityFlagGroup(),
|
||||
}
|
||||
rootfsFlags.ReportFlagGroup.ReportFormat = nil // TODO: support --report summary
|
||||
rootfsFlags.ReportFlagGroup.Compliance = nil // disable '--compliance'
|
||||
rootfsFlags.ReportFlagGroup.ReportFormat = nil // disable '--report'
|
||||
rootfsFlags.PackageFlagGroup.IncludeDevDeps = nil // disable '--include-dev-deps'
|
||||
rootfsFlags.CacheFlagGroup.CacheBackend.Default = string(cache.TypeMemory) // Use memory cache by default
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "rootfs [flags] ROOTDIR",
|
||||
@@ -455,28 +468,31 @@ func NewRootfsCommand(globalFlags *flag.GlobalFlagGroup) *cobra.Command {
|
||||
}
|
||||
|
||||
func NewRepositoryCommand(globalFlags *flag.GlobalFlagGroup) *cobra.Command {
|
||||
repoFlags := &flag.Flags{
|
||||
GlobalFlagGroup: globalFlags,
|
||||
CacheFlagGroup: flag.NewCacheFlagGroup(),
|
||||
DBFlagGroup: flag.NewDBFlagGroup(),
|
||||
LicenseFlagGroup: flag.NewLicenseFlagGroup(),
|
||||
MisconfFlagGroup: flag.NewMisconfFlagGroup(),
|
||||
ModuleFlagGroup: flag.NewModuleFlagGroup(),
|
||||
PackageFlagGroup: flag.NewPackageFlagGroup(),
|
||||
RegistryFlagGroup: flag.NewRegistryFlagGroup(),
|
||||
RegoFlagGroup: flag.NewRegoFlagGroup(),
|
||||
RemoteFlagGroup: flag.NewClientFlags(), // for client/server mode
|
||||
ReportFlagGroup: flag.NewReportFlagGroup(),
|
||||
ScanFlagGroup: flag.NewScanFlagGroup(),
|
||||
SecretFlagGroup: flag.NewSecretFlagGroup(),
|
||||
VulnerabilityFlagGroup: flag.NewVulnerabilityFlagGroup(),
|
||||
RepoFlagGroup: flag.NewRepoFlagGroup(),
|
||||
}
|
||||
repoFlags.ReportFlagGroup.ReportFormat = nil // TODO: support --report summary
|
||||
repoFlags.ReportFlagGroup.Compliance = nil // disable '--compliance'
|
||||
repoFlags.ReportFlagGroup.ExitOnEOL = nil // disable '--exit-on-eol'
|
||||
reportFlagGroup := flag.NewReportFlagGroup()
|
||||
reportFlagGroup.ReportFormat = nil // TODO: support --report summary
|
||||
reportFlagGroup.Compliance = nil // disable '--compliance'
|
||||
reportFlagGroup.ExitOnEOL = nil // disable '--exit-on-eol'
|
||||
|
||||
repoFlags.ScanFlagGroup.DistroFlag = nil // `repo` subcommand doesn't support scanning OS packages, so we can disable `--distro`
|
||||
scanFlagGroup := flag.NewScanFlagGroup()
|
||||
scanFlagGroup.DistroFlag = nil // repo subcommand doesn't support scanning OS packages
|
||||
|
||||
repoFlags := flag.Flags{
|
||||
globalFlags,
|
||||
flag.NewCacheFlagGroup(),
|
||||
flag.NewDBFlagGroup(),
|
||||
flag.NewLicenseFlagGroup(),
|
||||
flag.NewMisconfFlagGroup(),
|
||||
flag.NewModuleFlagGroup(),
|
||||
flag.NewPackageFlagGroup(),
|
||||
flag.NewRegistryFlagGroup(),
|
||||
flag.NewRegoFlagGroup(),
|
||||
flag.NewClientFlags(), // for client/server mode
|
||||
reportFlagGroup,
|
||||
scanFlagGroup,
|
||||
flag.NewSecretFlagGroup(),
|
||||
flag.NewVulnerabilityFlagGroup(),
|
||||
flag.NewRepoFlagGroup(),
|
||||
}
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "repository [flags] (REPO_PATH | REPO_URL)",
|
||||
@@ -514,18 +530,20 @@ func NewRepositoryCommand(globalFlags *flag.GlobalFlagGroup) *cobra.Command {
|
||||
}
|
||||
|
||||
func NewConvertCommand(globalFlags *flag.GlobalFlagGroup) *cobra.Command {
|
||||
convertFlags := &flag.Flags{
|
||||
GlobalFlagGroup: globalFlags,
|
||||
ScanFlagGroup: &flag.ScanFlagGroup{},
|
||||
ReportFlagGroup: flag.NewReportFlagGroup(),
|
||||
}
|
||||
|
||||
// To display the summary table, we need to enable scanners (to build columns).
|
||||
// We can't get scanner information from the report (we don't include empty licenses and secrets in the report).
|
||||
// So we need to ask the user to configure scanners (if needed).
|
||||
convertFlags.ScanFlagGroup.Scanners = flag.ScannersFlag.Clone()
|
||||
convertFlags.ScanFlagGroup.Scanners.Default = nil // disable default scanners
|
||||
convertFlags.ScanFlagGroup.Scanners.Usage = "List of scanners included when generating the json report. Used only for rendering the summary table."
|
||||
scanFlagGroup := &flag.ScanFlagGroup{
|
||||
Scanners: flag.ScannersFlag.Clone(),
|
||||
}
|
||||
scanFlagGroup.Scanners.Default = nil // disable default scanners
|
||||
scanFlagGroup.Scanners.Usage = "List of scanners included when generating the json report. Used only for rendering the summary table."
|
||||
|
||||
convertFlags := flag.Flags{
|
||||
globalFlags,
|
||||
scanFlagGroup,
|
||||
flag.NewReportFlagGroup(),
|
||||
}
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "convert [flags] RESULT_JSON",
|
||||
@@ -575,17 +593,17 @@ func NewClientCommand(globalFlags *flag.GlobalFlagGroup) *cobra.Command {
|
||||
}
|
||||
remoteFlags.ServerAddr = &remoteAddr // disable '--server' and enable '--remote' instead.
|
||||
|
||||
clientFlags := &flag.Flags{
|
||||
GlobalFlagGroup: globalFlags,
|
||||
CacheFlagGroup: flag.NewCacheFlagGroup(),
|
||||
DBFlagGroup: flag.NewDBFlagGroup(),
|
||||
MisconfFlagGroup: flag.NewMisconfFlagGroup(),
|
||||
RegistryFlagGroup: flag.NewRegistryFlagGroup(),
|
||||
RegoFlagGroup: flag.NewRegoFlagGroup(),
|
||||
RemoteFlagGroup: remoteFlags,
|
||||
ReportFlagGroup: flag.NewReportFlagGroup(),
|
||||
ScanFlagGroup: flag.NewScanFlagGroup(),
|
||||
VulnerabilityFlagGroup: flag.NewVulnerabilityFlagGroup(),
|
||||
clientFlags := flag.Flags{
|
||||
globalFlags,
|
||||
flag.NewCacheFlagGroup(),
|
||||
flag.NewDBFlagGroup(),
|
||||
flag.NewMisconfFlagGroup(),
|
||||
flag.NewRegistryFlagGroup(),
|
||||
flag.NewRegoFlagGroup(),
|
||||
remoteFlags,
|
||||
flag.NewReportFlagGroup(),
|
||||
flag.NewScanFlagGroup(),
|
||||
flag.NewVulnerabilityFlagGroup(),
|
||||
}
|
||||
|
||||
cmd := &cobra.Command{
|
||||
@@ -621,19 +639,20 @@ func NewClientCommand(globalFlags *flag.GlobalFlagGroup) *cobra.Command {
|
||||
}
|
||||
|
||||
func NewServerCommand(globalFlags *flag.GlobalFlagGroup) *cobra.Command {
|
||||
serverFlags := &flag.Flags{
|
||||
GlobalFlagGroup: globalFlags,
|
||||
CacheFlagGroup: flag.NewCacheFlagGroup(),
|
||||
DBFlagGroup: flag.NewDBFlagGroup(),
|
||||
ModuleFlagGroup: flag.NewModuleFlagGroup(),
|
||||
RemoteFlagGroup: flag.NewServerFlags(),
|
||||
RegistryFlagGroup: flag.NewRegistryFlagGroup(),
|
||||
}
|
||||
// The Java DB is not needed for the server mode
|
||||
dbFlagGroup := flag.NewDBFlagGroup()
|
||||
dbFlagGroup.DownloadJavaDBOnly = nil // disable '--download-java-db-only'
|
||||
dbFlagGroup.SkipJavaDBUpdate = nil // disable '--skip-java-db-update'
|
||||
dbFlagGroup.JavaDBRepositories = nil // disable '--java-db-repository'
|
||||
|
||||
// java-db only works on client side.
|
||||
serverFlags.DBFlagGroup.DownloadJavaDBOnly = nil // disable '--download-java-db-only'
|
||||
serverFlags.DBFlagGroup.SkipJavaDBUpdate = nil // disable '--skip-java-db-update'
|
||||
serverFlags.DBFlagGroup.JavaDBRepositories = nil // disable '--java-db-repository'
|
||||
serverFlags := flag.Flags{
|
||||
globalFlags,
|
||||
flag.NewCacheFlagGroup(),
|
||||
dbFlagGroup,
|
||||
flag.NewModuleFlagGroup(),
|
||||
flag.NewServerFlags(),
|
||||
flag.NewRegistryFlagGroup(),
|
||||
}
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "server [flags]",
|
||||
@@ -675,28 +694,31 @@ func NewConfigCommand(globalFlags *flag.GlobalFlagGroup) *cobra.Command {
|
||||
FilePatterns: flag.FilePatternsFlag.Clone(),
|
||||
}
|
||||
|
||||
reportFlagGroup := flag.NewReportFlagGroup()
|
||||
reportFlagGroup.DependencyTree = nil // disable '--dependency-tree'
|
||||
reportFlagGroup.ListAllPkgs = nil // disable '--list-all-pkgs'
|
||||
reportFlagGroup.ExitOnEOL = nil // disable '--exit-on-eol'
|
||||
reportFlagGroup.ShowSuppressed = nil // disable '--show-suppressed'
|
||||
reportFlagGroup.ReportFormat.Usage = "specify a compliance report format for the output" // @TODO: support --report summary for non compliance reports
|
||||
|
||||
cacheFlagGroup := flag.NewCacheFlagGroup()
|
||||
cacheFlagGroup.CacheBackend.Default = string(cache.TypeMemory)
|
||||
|
||||
configFlags := &flag.Flags{
|
||||
GlobalFlagGroup: globalFlags,
|
||||
CacheFlagGroup: flag.NewCacheFlagGroup(),
|
||||
MisconfFlagGroup: flag.NewMisconfFlagGroup(),
|
||||
ModuleFlagGroup: flag.NewModuleFlagGroup(),
|
||||
RegistryFlagGroup: flag.NewRegistryFlagGroup(),
|
||||
RegoFlagGroup: flag.NewRegoFlagGroup(),
|
||||
K8sFlagGroup: &flag.K8sFlagGroup{
|
||||
// disable unneeded flags
|
||||
globalFlags,
|
||||
cacheFlagGroup,
|
||||
flag.NewMisconfFlagGroup(),
|
||||
flag.NewModuleFlagGroup(),
|
||||
flag.NewRegistryFlagGroup(),
|
||||
flag.NewRegoFlagGroup(),
|
||||
&flag.K8sFlagGroup{
|
||||
// Keep only --k8s-version flag and disable others
|
||||
K8sVersion: flag.K8sVersionFlag.Clone(),
|
||||
},
|
||||
ReportFlagGroup: flag.NewReportFlagGroup(),
|
||||
ScanFlagGroup: scanFlags,
|
||||
reportFlagGroup,
|
||||
scanFlags,
|
||||
}
|
||||
|
||||
configFlags.ReportFlagGroup.DependencyTree = nil // disable '--dependency-tree'
|
||||
configFlags.ReportFlagGroup.ListAllPkgs = nil // disable '--list-all-pkgs'
|
||||
configFlags.ReportFlagGroup.ExitOnEOL = nil // disable '--exit-on-eol'
|
||||
configFlags.ReportFlagGroup.ShowSuppressed = nil // disable '--show-suppressed'
|
||||
configFlags.ReportFlagGroup.ReportFormat.Usage = "specify a compliance report format for the output" // @TODO: support --report summary for non compliance reports
|
||||
configFlags.CacheFlagGroup.CacheBackend.Default = string(cache.TypeMemory)
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "config [flags] DIR",
|
||||
Aliases: []string{"conf"},
|
||||
@@ -738,7 +760,7 @@ func NewConfigCommand(globalFlags *flag.GlobalFlagGroup) *cobra.Command {
|
||||
func NewPluginCommand(globalFlags *flag.GlobalFlagGroup) *cobra.Command {
|
||||
var pluginOptions flag.Options
|
||||
pluginFlags := &flag.Flags{
|
||||
GlobalFlagGroup: globalFlags,
|
||||
globalFlags,
|
||||
}
|
||||
cmd := &cobra.Command{
|
||||
Use: "plugin subcommand",
|
||||
@@ -747,7 +769,8 @@ func NewPluginCommand(globalFlags *flag.GlobalFlagGroup) *cobra.Command {
|
||||
Short: "Manage plugins",
|
||||
SilenceErrors: true,
|
||||
SilenceUsage: true,
|
||||
PersistentPreRunE: func(cmd *cobra.Command, args []string) (err error) {
|
||||
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
|
||||
var err error
|
||||
pluginOptions, err = pluginFlags.ToOptions(args)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -887,8 +910,8 @@ func NewPluginCommand(globalFlags *flag.GlobalFlagGroup) *cobra.Command {
|
||||
|
||||
func NewModuleCommand(globalFlags *flag.GlobalFlagGroup) *cobra.Command {
|
||||
moduleFlags := &flag.Flags{
|
||||
GlobalFlagGroup: globalFlags,
|
||||
ModuleFlagGroup: flag.NewModuleFlagGroup(),
|
||||
globalFlags,
|
||||
flag.NewModuleFlagGroup(),
|
||||
}
|
||||
|
||||
cmd := &cobra.Command{
|
||||
@@ -998,22 +1021,24 @@ func NewKubernetesCommand(globalFlags *flag.GlobalFlagGroup) *cobra.Command {
|
||||
misconfFlagGroup.CloudformationParamVars = nil // disable '--cf-params'
|
||||
misconfFlagGroup.TerraformTFVars = nil // disable '--tf-vars'
|
||||
|
||||
packageFlagGroup := flag.NewPackageFlagGroup()
|
||||
packageFlagGroup.IncludeDevDeps = nil // disable '--include-dev-deps'
|
||||
|
||||
k8sFlags := &flag.Flags{
|
||||
GlobalFlagGroup: globalFlags,
|
||||
CacheFlagGroup: flag.NewCacheFlagGroup(),
|
||||
DBFlagGroup: flag.NewDBFlagGroup(),
|
||||
ImageFlagGroup: imageFlags,
|
||||
K8sFlagGroup: flag.NewK8sFlagGroup(), // kubernetes-specific flags
|
||||
MisconfFlagGroup: misconfFlagGroup,
|
||||
PackageFlagGroup: flag.NewPackageFlagGroup(),
|
||||
RegoFlagGroup: flag.NewRegoFlagGroup(),
|
||||
ReportFlagGroup: reportFlagGroup,
|
||||
ScanFlagGroup: scanFlags,
|
||||
SecretFlagGroup: flag.NewSecretFlagGroup(),
|
||||
RegistryFlagGroup: flag.NewRegistryFlagGroup(),
|
||||
VulnerabilityFlagGroup: flag.NewVulnerabilityFlagGroup(),
|
||||
globalFlags,
|
||||
flag.NewCacheFlagGroup(),
|
||||
flag.NewDBFlagGroup(),
|
||||
imageFlags,
|
||||
flag.NewK8sFlagGroup(), // kubernetes-specific flags
|
||||
misconfFlagGroup,
|
||||
packageFlagGroup,
|
||||
flag.NewRegoFlagGroup(),
|
||||
reportFlagGroup,
|
||||
scanFlags,
|
||||
flag.NewSecretFlagGroup(),
|
||||
flag.NewRegistryFlagGroup(),
|
||||
flag.NewVulnerabilityFlagGroup(),
|
||||
}
|
||||
k8sFlags.PackageFlagGroup.IncludeDevDeps = nil // disable '--include-dev-deps'
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "kubernetes [flags] [CONTEXT]",
|
||||
@@ -1060,19 +1085,29 @@ func NewKubernetesCommand(globalFlags *flag.GlobalFlagGroup) *cobra.Command {
|
||||
}
|
||||
|
||||
func NewVMCommand(globalFlags *flag.GlobalFlagGroup) *cobra.Command {
|
||||
reportFlagGroup := flag.NewReportFlagGroup()
|
||||
reportFlagGroup.ReportFormat = nil // disable '--report'
|
||||
|
||||
packageFlagGroup := flag.NewPackageFlagGroup()
|
||||
packageFlagGroup.IncludeDevDeps = nil // disable '--include-dev-deps'
|
||||
|
||||
misconfFlagGroup := flag.NewMisconfFlagGroup()
|
||||
misconfFlagGroup.CloudformationParamVars = nil // disable '--cf-params'
|
||||
misconfFlagGroup.TerraformTFVars = nil // disable '--tf-vars'
|
||||
|
||||
vmFlags := &flag.Flags{
|
||||
GlobalFlagGroup: globalFlags,
|
||||
CacheFlagGroup: flag.NewCacheFlagGroup(),
|
||||
DBFlagGroup: flag.NewDBFlagGroup(),
|
||||
MisconfFlagGroup: flag.NewMisconfFlagGroup(),
|
||||
ModuleFlagGroup: flag.NewModuleFlagGroup(),
|
||||
PackageFlagGroup: flag.NewPackageFlagGroup(),
|
||||
RemoteFlagGroup: flag.NewClientFlags(), // for client/server mode
|
||||
ReportFlagGroup: flag.NewReportFlagGroup(),
|
||||
ScanFlagGroup: flag.NewScanFlagGroup(),
|
||||
SecretFlagGroup: flag.NewSecretFlagGroup(),
|
||||
VulnerabilityFlagGroup: flag.NewVulnerabilityFlagGroup(),
|
||||
AWSFlagGroup: &flag.AWSFlagGroup{
|
||||
globalFlags,
|
||||
flag.NewCacheFlagGroup(),
|
||||
flag.NewDBFlagGroup(),
|
||||
misconfFlagGroup,
|
||||
flag.NewModuleFlagGroup(),
|
||||
packageFlagGroup,
|
||||
flag.NewClientFlags(), // for client/server mode
|
||||
reportFlagGroup,
|
||||
flag.NewScanFlagGroup(),
|
||||
flag.NewSecretFlagGroup(),
|
||||
flag.NewVulnerabilityFlagGroup(),
|
||||
&flag.AWSFlagGroup{
|
||||
Region: &flag.Flag[string]{
|
||||
Name: "aws-region",
|
||||
ConfigName: "aws.region",
|
||||
@@ -1080,10 +1115,6 @@ func NewVMCommand(globalFlags *flag.GlobalFlagGroup) *cobra.Command {
|
||||
},
|
||||
},
|
||||
}
|
||||
vmFlags.ReportFlagGroup.ReportFormat = nil // disable '--report'
|
||||
vmFlags.PackageFlagGroup.IncludeDevDeps = nil // disable '--include-dev-deps'
|
||||
vmFlags.MisconfFlagGroup.CloudformationParamVars = nil // disable '--cf-params'
|
||||
vmFlags.MisconfFlagGroup.TerraformTFVars = nil // disable '--tf-vars'
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "vm [flags] VM_IMAGE",
|
||||
@@ -1148,21 +1179,24 @@ func NewSBOMCommand(globalFlags *flag.GlobalFlagGroup) *cobra.Command {
|
||||
licenseFlagGroup.LicenseFull = nil
|
||||
licenseFlagGroup.LicenseConfidenceLevel = nil
|
||||
|
||||
sbomFlags := &flag.Flags{
|
||||
GlobalFlagGroup: globalFlags,
|
||||
CacheFlagGroup: flag.NewCacheFlagGroup(),
|
||||
DBFlagGroup: flag.NewDBFlagGroup(),
|
||||
PackageFlagGroup: flag.NewPackageFlagGroup(),
|
||||
RemoteFlagGroup: flag.NewClientFlags(), // for client/server mode
|
||||
RegistryFlagGroup: flag.NewRegistryFlagGroup(), // for DBs in private registries
|
||||
ReportFlagGroup: reportFlagGroup,
|
||||
ScanFlagGroup: scanFlagGroup,
|
||||
VulnerabilityFlagGroup: flag.NewVulnerabilityFlagGroup(),
|
||||
LicenseFlagGroup: licenseFlagGroup,
|
||||
}
|
||||
cacheFlagGroup := flag.NewCacheFlagGroup()
|
||||
cacheFlagGroup.CacheBackend.Default = string(cache.TypeMemory) // Use memory cache by default
|
||||
|
||||
sbomFlags.CacheFlagGroup.CacheBackend.Default = string(cache.TypeMemory) // Use memory cache by default
|
||||
sbomFlags.PackageFlagGroup.IncludeDevDeps = nil // disable '--include-dev-deps'
|
||||
packageFlagGroup := flag.NewPackageFlagGroup()
|
||||
packageFlagGroup.IncludeDevDeps = nil // disable '--include-dev-deps'
|
||||
|
||||
sbomFlags := &flag.Flags{
|
||||
globalFlags,
|
||||
cacheFlagGroup,
|
||||
flag.NewDBFlagGroup(),
|
||||
packageFlagGroup,
|
||||
flag.NewClientFlags(), // for client/server mode
|
||||
flag.NewRegistryFlagGroup(), // for DBs in private registries
|
||||
reportFlagGroup,
|
||||
scanFlagGroup,
|
||||
flag.NewVulnerabilityFlagGroup(),
|
||||
licenseFlagGroup,
|
||||
}
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "sbom [flags] SBOM_PATH",
|
||||
@@ -1203,8 +1237,8 @@ func NewSBOMCommand(globalFlags *flag.GlobalFlagGroup) *cobra.Command {
|
||||
|
||||
func NewCleanCommand(globalFlags *flag.GlobalFlagGroup) *cobra.Command {
|
||||
cleanFlags := &flag.Flags{
|
||||
GlobalFlagGroup: globalFlags,
|
||||
CleanFlagGroup: flag.NewCleanFlagGroup(),
|
||||
globalFlags,
|
||||
flag.NewCleanFlagGroup(),
|
||||
}
|
||||
cmd := &cobra.Command{
|
||||
Use: "clean [flags]",
|
||||
@@ -1252,11 +1286,13 @@ func NewRegistryCommand(globalFlags *flag.GlobalFlagGroup) *cobra.Command {
|
||||
SilenceUsage: true,
|
||||
}
|
||||
|
||||
registryFlagGroup := flag.NewRegistryFlagGroup()
|
||||
registryFlagGroup.RegistryToken = nil
|
||||
|
||||
loginFlags := &flag.Flags{
|
||||
GlobalFlagGroup: globalFlags,
|
||||
RegistryFlagGroup: flag.NewRegistryFlagGroup(),
|
||||
globalFlags,
|
||||
registryFlagGroup,
|
||||
}
|
||||
loginFlags.RegistryFlagGroup.RegistryToken = nil // disable '--registry-token'
|
||||
loginCmd := &cobra.Command{
|
||||
Use: "login SERVER",
|
||||
Short: "Log in to a registry",
|
||||
@@ -1300,23 +1336,25 @@ func NewRegistryCommand(globalFlags *flag.GlobalFlagGroup) *cobra.Command {
|
||||
}
|
||||
|
||||
func NewVEXCommand(globalFlags *flag.GlobalFlagGroup) *cobra.Command {
|
||||
vexFlags := &flag.Flags{
|
||||
GlobalFlagGroup: globalFlags,
|
||||
vexFlags := flag.Flags{
|
||||
globalFlags,
|
||||
}
|
||||
var vexOptions flag.Options
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "vex subcommand",
|
||||
GroupID: groupManagement,
|
||||
Short: "[EXPERIMENTAL] VEX utilities",
|
||||
SilenceErrors: true,
|
||||
SilenceUsage: true,
|
||||
PersistentPreRunE: func(cmd *cobra.Command, args []string) (err error) {
|
||||
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
|
||||
cmd.SetContext(log.WithContextPrefix(cmd.Context(), "vex"))
|
||||
|
||||
vexOptions, err = vexFlags.ToOptions(args)
|
||||
opts, err := vexFlags.ToOptions(args)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
vexOptions = opts
|
||||
return nil
|
||||
},
|
||||
}
|
||||
@@ -1393,11 +1431,12 @@ func NewVersionCommand(globalFlags *flag.GlobalFlagGroup) *cobra.Command {
|
||||
GroupID: groupUtility,
|
||||
Args: cobra.NoArgs,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
options, err := globalFlags.ToOptions()
|
||||
flags := flag.Flags{globalFlags}
|
||||
opts, err := flags.ToOptions(args)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return showVersion(options.CacheDir, versionFormat, cmd.OutOrStdout())
|
||||
return showVersion(opts.CacheDir, versionFormat, cmd.OutOrStdout())
|
||||
},
|
||||
SilenceErrors: true,
|
||||
SilenceUsage: true,
|
||||
|
||||
@@ -315,9 +315,9 @@ func TestFlags(t *testing.T) {
|
||||
rootCmd.SetOut(io.Discard)
|
||||
|
||||
flags := &flag.Flags{
|
||||
GlobalFlagGroup: globalFlags,
|
||||
ReportFlagGroup: flag.NewReportFlagGroup(),
|
||||
ScanFlagGroup: flag.NewScanFlagGroup(),
|
||||
globalFlags,
|
||||
flag.NewReportFlagGroup(),
|
||||
flag.NewScanFlagGroup(),
|
||||
}
|
||||
cmd := &cobra.Command{
|
||||
Use: "test",
|
||||
|
||||
@@ -77,16 +77,14 @@ func (f *AWSFlagGroup) Flags() []Flagger {
|
||||
}
|
||||
}
|
||||
|
||||
func (f *AWSFlagGroup) ToOptions() (AWSOptions, error) {
|
||||
if err := parseFlags(f); err != nil {
|
||||
return AWSOptions{}, err
|
||||
}
|
||||
return AWSOptions{
|
||||
func (f *AWSFlagGroup) ToOptions(opts *Options) error {
|
||||
opts.AWSOptions = AWSOptions{
|
||||
Region: f.Region.Value(),
|
||||
Endpoint: f.Endpoint.Value(),
|
||||
Services: f.Services.Value(),
|
||||
SkipServices: f.SkipServices.Value(),
|
||||
Account: f.Account.Value(),
|
||||
ARN: f.ARN.Value(),
|
||||
}, nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -106,17 +106,15 @@ func (fg *CacheFlagGroup) Flags() []Flagger {
|
||||
}
|
||||
}
|
||||
|
||||
func (fg *CacheFlagGroup) ToOptions() (CacheOptions, error) {
|
||||
if err := parseFlags(fg); err != nil {
|
||||
return CacheOptions{}, err
|
||||
}
|
||||
|
||||
return CacheOptions{
|
||||
func (fg *CacheFlagGroup) ToOptions(opts *Options) error {
|
||||
opts.CacheOptions = CacheOptions{
|
||||
ClearCache: fg.ClearCache.Value(),
|
||||
CacheBackend: fg.CacheBackend.Value(),
|
||||
CacheTTL: fg.CacheTTL.Value(),
|
||||
RedisTLS: fg.RedisTLS.Value(),
|
||||
RedisCACert: fg.RedisCACert.Value(),
|
||||
RedisCert: fg.RedisCert.Value(),
|
||||
RedisKey: fg.RedisKey.Value(),
|
||||
}, nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -78,17 +78,14 @@ func (fg *CleanFlagGroup) Flags() []Flagger {
|
||||
}
|
||||
}
|
||||
|
||||
func (fg *CleanFlagGroup) ToOptions() (CleanOptions, error) {
|
||||
if err := parseFlags(fg); err != nil {
|
||||
return CleanOptions{}, err
|
||||
}
|
||||
|
||||
return CleanOptions{
|
||||
func (fg *CleanFlagGroup) ToOptions(opts *Options) error {
|
||||
opts.CleanOptions = CleanOptions{
|
||||
CleanAll: fg.CleanAll.Value(),
|
||||
CleanVulnerabilityDB: fg.CleanVulnerabilityDB.Value(),
|
||||
CleanJavaDB: fg.CleanJavaDB.Value(),
|
||||
CleanChecksBundle: fg.CleanChecksBundle.Value(),
|
||||
CleanScanCache: fg.CleanScanCache.Value(),
|
||||
CleanVEXRepositories: fg.CleanVEXRepositories.Value(),
|
||||
}, nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -127,31 +127,27 @@ func (f *DBFlagGroup) Flags() []Flagger {
|
||||
}
|
||||
}
|
||||
|
||||
func (f *DBFlagGroup) ToOptions() (DBOptions, error) {
|
||||
if err := parseFlags(f); err != nil {
|
||||
return DBOptions{}, err
|
||||
}
|
||||
|
||||
func (f *DBFlagGroup) ToOptions(opts *Options) error {
|
||||
skipDBUpdate := f.SkipDBUpdate.Value()
|
||||
skipJavaDBUpdate := f.SkipJavaDBUpdate.Value()
|
||||
downloadDBOnly := f.DownloadDBOnly.Value()
|
||||
downloadJavaDBOnly := f.DownloadJavaDBOnly.Value()
|
||||
|
||||
if downloadDBOnly && downloadJavaDBOnly {
|
||||
return DBOptions{}, xerrors.New("--download-db-only and --download-java-db-only options can not be specified both")
|
||||
return xerrors.New("--download-db-only and --download-java-db-only options can not be specified both")
|
||||
}
|
||||
if downloadDBOnly && skipDBUpdate {
|
||||
return DBOptions{}, xerrors.New("--skip-db-update and --download-db-only options can not be specified both")
|
||||
return xerrors.New("--skip-db-update and --download-db-only options can not be specified both")
|
||||
}
|
||||
if downloadJavaDBOnly && skipJavaDBUpdate {
|
||||
return DBOptions{}, xerrors.New("--skip-java-db-update and --download-java-db-only options can not be specified both")
|
||||
return xerrors.New("--skip-java-db-update and --download-java-db-only options can not be specified both")
|
||||
}
|
||||
|
||||
var dbRepositories, javaDBRepositories []name.Reference
|
||||
for _, repo := range f.DBRepositories.Value() {
|
||||
ref, err := parseRepository(repo, db.SchemaVersion)
|
||||
if err != nil {
|
||||
return DBOptions{}, xerrors.Errorf("invalid DB repository: %w", err)
|
||||
return xerrors.Errorf("invalid DB repository: %w", err)
|
||||
}
|
||||
dbRepositories = append(dbRepositories, ref)
|
||||
}
|
||||
@@ -159,12 +155,12 @@ func (f *DBFlagGroup) ToOptions() (DBOptions, error) {
|
||||
for _, repo := range f.JavaDBRepositories.Value() {
|
||||
ref, err := parseRepository(repo, javadb.SchemaVersion)
|
||||
if err != nil {
|
||||
return DBOptions{}, xerrors.Errorf("invalid javadb repository: %w", err)
|
||||
return xerrors.Errorf("invalid javadb repository: %w", err)
|
||||
}
|
||||
javaDBRepositories = append(javaDBRepositories, ref)
|
||||
}
|
||||
|
||||
return DBOptions{
|
||||
opts.DBOptions = DBOptions{
|
||||
Reset: f.Reset.Value(),
|
||||
DownloadDBOnly: downloadDBOnly,
|
||||
SkipDBUpdate: skipDBUpdate,
|
||||
@@ -173,7 +169,8 @@ func (f *DBFlagGroup) ToOptions() (DBOptions, error) {
|
||||
NoProgress: f.NoProgress.Value(),
|
||||
DBRepositories: dbRepositories,
|
||||
JavaDBRepositories: javaDBRepositories,
|
||||
}, nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func parseRepository(repo string, dbSchemaVersion int) (name.Reference, error) {
|
||||
|
||||
@@ -101,15 +101,15 @@ func TestDBFlagGroup_ToOptions(t *testing.T) {
|
||||
DBRepositories: flag.DBRepositoryFlag.Clone(),
|
||||
JavaDBRepositories: flag.JavaDBRepositoryFlag.Clone(),
|
||||
}
|
||||
got, err := f.ToOptions()
|
||||
flags := flag.Flags{f}
|
||||
got, err := flags.ToOptions(nil)
|
||||
if tt.wantErr != "" {
|
||||
require.Error(t, err)
|
||||
assert.ErrorContains(t, err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.EqualExportedValues(t, tt.want, got)
|
||||
assert.EqualExportedValues(t, tt.want, got.DBOptions)
|
||||
|
||||
// Assert log messages
|
||||
assert.Equal(t, tt.wantLogs, out.Messages(), tt.name)
|
||||
|
||||
@@ -137,17 +137,13 @@ func (f *GlobalFlagGroup) Bind(cmd *cobra.Command) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *GlobalFlagGroup) ToOptions() (GlobalOptions, error) {
|
||||
if err := parseFlags(f); err != nil {
|
||||
return GlobalOptions{}, err
|
||||
}
|
||||
|
||||
func (f *GlobalFlagGroup) ToOptions(opts *Options) error {
|
||||
// Keep TRIVY_NON_SSL for backward compatibility
|
||||
insecure := f.Insecure.Value() || os.Getenv("TRIVY_NON_SSL") != ""
|
||||
|
||||
log.Debug("Cache dir", log.String("dir", f.CacheDir.Value()))
|
||||
|
||||
return GlobalOptions{
|
||||
opts.GlobalOptions = GlobalOptions{
|
||||
ConfigFile: f.ConfigFile.Value(),
|
||||
ShowVersion: f.ShowVersion.Value(),
|
||||
Quiet: f.Quiet.Value(),
|
||||
@@ -156,5 +152,6 @@ func (f *GlobalFlagGroup) ToOptions() (GlobalOptions, error) {
|
||||
Timeout: f.Timeout.Value(),
|
||||
CacheDir: f.CacheDir.Value(),
|
||||
GenerateDefaultConfig: f.GenerateDefaultConfig.Value(),
|
||||
}, nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -119,16 +119,12 @@ func (f *ImageFlagGroup) Flags() []Flagger {
|
||||
}
|
||||
}
|
||||
|
||||
func (f *ImageFlagGroup) ToOptions() (ImageOptions, error) {
|
||||
if err := parseFlags(f); err != nil {
|
||||
return ImageOptions{}, err
|
||||
}
|
||||
|
||||
func (f *ImageFlagGroup) ToOptions(opts *Options) error {
|
||||
var platform ftypes.Platform
|
||||
if p := f.Platform.Value(); p != "" {
|
||||
pl, err := v1.ParsePlatform(p)
|
||||
if err != nil {
|
||||
return ImageOptions{}, xerrors.Errorf("unable to parse platform: %w", err)
|
||||
return xerrors.Errorf("unable to parse platform: %w", err)
|
||||
}
|
||||
if pl.OS == "*" {
|
||||
pl.OS = "" // Empty OS means any OS
|
||||
@@ -139,12 +135,12 @@ func (f *ImageFlagGroup) ToOptions() (ImageOptions, error) {
|
||||
if value := f.MaxImageSize.Value(); value != "" {
|
||||
parsedSize, err := units.FromHumanSize(value)
|
||||
if err != nil {
|
||||
return ImageOptions{}, xerrors.Errorf("invalid max image size %q: %w", value, err)
|
||||
return xerrors.Errorf("invalid max image size %q: %w", value, err)
|
||||
}
|
||||
maxSize = parsedSize
|
||||
}
|
||||
|
||||
return ImageOptions{
|
||||
opts.ImageOptions = ImageOptions{
|
||||
Input: f.Input.Value(),
|
||||
ImageConfigScanners: xstrings.ToTSlice[types.Scanner](f.ImageConfigScanners.Value()),
|
||||
ScanRemovedPkgs: f.ScanRemovedPkgs.Value(),
|
||||
@@ -153,5 +149,6 @@ func (f *ImageFlagGroup) ToOptions() (ImageOptions, error) {
|
||||
PodmanHost: f.PodmanHost.Value(),
|
||||
ImageSources: xstrings.ToTSlice[ftypes.ImageSource](f.ImageSources.Value()),
|
||||
MaxImageSize: maxSize,
|
||||
}, nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -79,13 +79,14 @@ func TestImageFlagGroup_ToOptions(t *testing.T) {
|
||||
Platform: flag.PlatformFlag.Clone(),
|
||||
}
|
||||
|
||||
got, err := f.ToOptions()
|
||||
flags := flag.Flags{f}
|
||||
got, err := flags.ToOptions(nil)
|
||||
if tt.wantErr != "" {
|
||||
assert.ErrorContains(t, err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
require.NoError(t, err)
|
||||
assert.EqualExportedValues(t, tt.want, got)
|
||||
assert.EqualExportedValues(t, tt.want, got.ImageOptions)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,11 +2,11 @@ package flag
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/samber/lo"
|
||||
"golang.org/x/xerrors"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
)
|
||||
|
||||
@@ -173,14 +173,10 @@ func (f *K8sFlagGroup) Flags() []Flagger {
|
||||
}
|
||||
}
|
||||
|
||||
func (f *K8sFlagGroup) ToOptions() (K8sOptions, error) {
|
||||
if err := parseFlags(f); err != nil {
|
||||
return K8sOptions{}, err
|
||||
}
|
||||
|
||||
func (f *K8sFlagGroup) ToOptions(opts *Options) error {
|
||||
tolerations, err := optionToTolerations(f.Tolerations.Value())
|
||||
if err != nil {
|
||||
return K8sOptions{}, err
|
||||
return err
|
||||
}
|
||||
|
||||
exludeNodeLabels := make(map[string]string)
|
||||
@@ -188,18 +184,18 @@ func (f *K8sFlagGroup) ToOptions() (K8sOptions, error) {
|
||||
for _, exludeNodeValue := range exludeNodes {
|
||||
excludeNodeParts := strings.Split(exludeNodeValue, ":")
|
||||
if len(excludeNodeParts) != 2 {
|
||||
return K8sOptions{}, fmt.Errorf("exclude node %s must be a key:value", exludeNodeValue)
|
||||
return xerrors.Errorf("exclude node %s must be a key:value", exludeNodeValue)
|
||||
}
|
||||
exludeNodeLabels[excludeNodeParts[0]] = excludeNodeParts[1]
|
||||
}
|
||||
if len(f.ExcludeNamespaces.Value()) > 0 && len(f.IncludeNamespaces.Value()) > 0 {
|
||||
return K8sOptions{}, errors.New("include-namespaces and exclude-namespaces flags cannot be used together")
|
||||
return xerrors.New("include-namespaces and exclude-namespaces flags cannot be used together")
|
||||
}
|
||||
if len(f.ExcludeKinds.Value()) > 0 && len(f.IncludeKinds.Value()) > 0 {
|
||||
return K8sOptions{}, errors.New("include-kinds and exclude-kinds flags cannot be used together")
|
||||
return xerrors.New("include-kinds and exclude-kinds flags cannot be used together")
|
||||
}
|
||||
|
||||
return K8sOptions{
|
||||
opts.K8sOptions = K8sOptions{
|
||||
KubeConfig: f.KubeConfig.Value(),
|
||||
K8sVersion: f.K8sVersion.Value(),
|
||||
Tolerations: tolerations,
|
||||
@@ -215,7 +211,8 @@ func (f *K8sFlagGroup) ToOptions() (K8sOptions, error) {
|
||||
ExcludeNamespaces: f.ExcludeNamespaces.Value(),
|
||||
IncludeNamespaces: f.IncludeNamespaces.Value(),
|
||||
Burst: f.Burst.Value(),
|
||||
}, nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func optionToTolerations(tolerationsOptions []string) ([]corev1.Toleration, error) {
|
||||
|
||||
@@ -115,11 +115,7 @@ func (f *LicenseFlagGroup) Flags() []Flagger {
|
||||
}
|
||||
}
|
||||
|
||||
func (f *LicenseFlagGroup) ToOptions() (LicenseOptions, error) {
|
||||
if err := parseFlags(f); err != nil {
|
||||
return LicenseOptions{}, err
|
||||
}
|
||||
|
||||
func (f *LicenseFlagGroup) ToOptions(opts *Options) error {
|
||||
licenseCategories := make(map[types.LicenseCategory][]string)
|
||||
licenseCategories[types.CategoryForbidden] = f.LicenseForbidden.Value()
|
||||
licenseCategories[types.CategoryRestricted] = f.LicenseRestricted.Value()
|
||||
@@ -128,10 +124,11 @@ func (f *LicenseFlagGroup) ToOptions() (LicenseOptions, error) {
|
||||
licenseCategories[types.CategoryPermissive] = f.LicensePermissive.Value()
|
||||
licenseCategories[types.CategoryUnencumbered] = f.LicenseUnencumbered.Value()
|
||||
|
||||
return LicenseOptions{
|
||||
opts.LicenseOptions = LicenseOptions{
|
||||
LicenseFull: f.LicenseFull.Value(),
|
||||
IgnoredLicenses: f.IgnoredLicenses.Value(),
|
||||
LicenseConfidenceLevel: f.LicenseConfidenceLevel.Value(),
|
||||
LicenseCategories: licenseCategories,
|
||||
}, nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -204,12 +204,8 @@ func (f *MisconfFlagGroup) Flags() []Flagger {
|
||||
}
|
||||
}
|
||||
|
||||
func (f *MisconfFlagGroup) ToOptions() (MisconfOptions, error) {
|
||||
if err := parseFlags(f); err != nil {
|
||||
return MisconfOptions{}, err
|
||||
}
|
||||
|
||||
return MisconfOptions{
|
||||
func (f *MisconfFlagGroup) ToOptions(opts *Options) error {
|
||||
opts.MisconfOptions = MisconfOptions{
|
||||
IncludeNonFailures: f.IncludeNonFailures.Value(),
|
||||
ResetChecksBundle: f.ResetChecksBundle.Value(),
|
||||
ChecksBundleRepository: f.ChecksBundleRepository.Value(),
|
||||
@@ -225,5 +221,6 @@ func (f *MisconfFlagGroup) ToOptions() (MisconfOptions, error) {
|
||||
MisconfigScanners: xstrings.ToTSlice[analyzer.Type](f.MisconfigScanners.Value()),
|
||||
ConfigFileSchemas: f.ConfigFileSchemas.Value(),
|
||||
RenderCause: xstrings.ToTSlice[types.ConfigType](f.RenderCause.Value()),
|
||||
}, nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -58,13 +58,10 @@ func (f *ModuleFlagGroup) Flags() []Flagger {
|
||||
}
|
||||
}
|
||||
|
||||
func (f *ModuleFlagGroup) ToOptions() (ModuleOptions, error) {
|
||||
if err := parseFlags(f); err != nil {
|
||||
return ModuleOptions{}, err
|
||||
}
|
||||
|
||||
return ModuleOptions{
|
||||
func (f *ModuleFlagGroup) ToOptions(opts *Options) error {
|
||||
opts.ModuleOptions = ModuleOptions{
|
||||
ModuleDir: f.Dir.Value(),
|
||||
EnabledModules: f.EnabledModules.Value(),
|
||||
}, nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -344,6 +344,7 @@ func (f *Flag[T]) BindEnv() error {
|
||||
type FlagGroup interface {
|
||||
Name() string
|
||||
Flags() []Flagger
|
||||
ToOptions(*Options) error
|
||||
}
|
||||
|
||||
type Flagger interface {
|
||||
@@ -358,27 +359,7 @@ type Flagger interface {
|
||||
Bind(cmd *cobra.Command) error
|
||||
}
|
||||
|
||||
type Flags struct {
|
||||
GlobalFlagGroup *GlobalFlagGroup
|
||||
AWSFlagGroup *AWSFlagGroup
|
||||
CacheFlagGroup *CacheFlagGroup
|
||||
CleanFlagGroup *CleanFlagGroup
|
||||
DBFlagGroup *DBFlagGroup
|
||||
ImageFlagGroup *ImageFlagGroup
|
||||
K8sFlagGroup *K8sFlagGroup
|
||||
LicenseFlagGroup *LicenseFlagGroup
|
||||
MisconfFlagGroup *MisconfFlagGroup
|
||||
ModuleFlagGroup *ModuleFlagGroup
|
||||
PackageFlagGroup *PackageFlagGroup
|
||||
RemoteFlagGroup *RemoteFlagGroup
|
||||
RegistryFlagGroup *RegistryFlagGroup
|
||||
RegoFlagGroup *RegoFlagGroup
|
||||
RepoFlagGroup *RepoFlagGroup
|
||||
ReportFlagGroup *ReportFlagGroup
|
||||
ScanFlagGroup *ScanFlagGroup
|
||||
SecretFlagGroup *SecretFlagGroup
|
||||
VulnerabilityFlagGroup *VulnerabilityFlagGroup
|
||||
}
|
||||
type Flags []FlagGroup
|
||||
|
||||
// Options holds all the runtime configuration
|
||||
type Options struct {
|
||||
@@ -411,15 +392,19 @@ type Options struct {
|
||||
// outputWriter is not initialized via the CLI.
|
||||
// It is mainly used for testing purposes or by tools that use Trivy as a library.
|
||||
outputWriter io.Writer
|
||||
|
||||
// args is the arguments passed to the command.
|
||||
args []string
|
||||
}
|
||||
|
||||
// Align takes consistency of options
|
||||
func (o *Options) Align(f *Flags) error {
|
||||
if f.ScanFlagGroup != nil && f.ScanFlagGroup.Scanners != nil {
|
||||
if scanFlagGroup, ok := findFlagGroup[*ScanFlagGroup](f); ok && scanFlagGroup.Scanners != nil {
|
||||
o.enableSBOM()
|
||||
}
|
||||
|
||||
if f.PackageFlagGroup != nil && f.PackageFlagGroup.PkgRelationships != nil &&
|
||||
if packageFlagGroup, ok := findFlagGroup[*PackageFlagGroup](f); ok &&
|
||||
packageFlagGroup.PkgRelationships != nil &&
|
||||
slices.Compare(o.PkgRelationships, ftypes.Relationships) != 0 &&
|
||||
(o.DependencyTree || slices.Contains(types.SupportedSBOMFormats, o.Format) || len(o.VEXSources) != 0) {
|
||||
return xerrors.Errorf("'--pkg-relationships' cannot be used with '--dependency-tree', '--vex' or SBOM formats")
|
||||
@@ -601,63 +586,9 @@ func (o *Options) outputPluginWriter(ctx context.Context) (io.Writer, func() err
|
||||
|
||||
// groups returns all the flag groups other than global flags
|
||||
func (f *Flags) groups() []FlagGroup {
|
||||
var groups []FlagGroup
|
||||
// This order affects the usage message, so they are sorted by frequency of use.
|
||||
if f.ScanFlagGroup != nil {
|
||||
groups = append(groups, f.ScanFlagGroup)
|
||||
}
|
||||
if f.ReportFlagGroup != nil {
|
||||
groups = append(groups, f.ReportFlagGroup)
|
||||
}
|
||||
if f.CacheFlagGroup != nil {
|
||||
groups = append(groups, f.CacheFlagGroup)
|
||||
}
|
||||
if f.CleanFlagGroup != nil {
|
||||
groups = append(groups, f.CleanFlagGroup)
|
||||
}
|
||||
if f.DBFlagGroup != nil {
|
||||
groups = append(groups, f.DBFlagGroup)
|
||||
}
|
||||
if f.RegistryFlagGroup != nil {
|
||||
groups = append(groups, f.RegistryFlagGroup)
|
||||
}
|
||||
if f.ImageFlagGroup != nil {
|
||||
groups = append(groups, f.ImageFlagGroup)
|
||||
}
|
||||
if f.VulnerabilityFlagGroup != nil {
|
||||
groups = append(groups, f.VulnerabilityFlagGroup)
|
||||
}
|
||||
if f.MisconfFlagGroup != nil {
|
||||
groups = append(groups, f.MisconfFlagGroup)
|
||||
}
|
||||
if f.ModuleFlagGroup != nil {
|
||||
groups = append(groups, f.ModuleFlagGroup)
|
||||
}
|
||||
if f.SecretFlagGroup != nil {
|
||||
groups = append(groups, f.SecretFlagGroup)
|
||||
}
|
||||
if f.LicenseFlagGroup != nil {
|
||||
groups = append(groups, f.LicenseFlagGroup)
|
||||
}
|
||||
if f.RegoFlagGroup != nil {
|
||||
groups = append(groups, f.RegoFlagGroup)
|
||||
}
|
||||
if f.AWSFlagGroup != nil {
|
||||
groups = append(groups, f.AWSFlagGroup)
|
||||
}
|
||||
if f.K8sFlagGroup != nil {
|
||||
groups = append(groups, f.K8sFlagGroup)
|
||||
}
|
||||
if f.PackageFlagGroup != nil {
|
||||
groups = append(groups, f.PackageFlagGroup)
|
||||
}
|
||||
if f.RemoteFlagGroup != nil {
|
||||
groups = append(groups, f.RemoteFlagGroup)
|
||||
}
|
||||
if f.RepoFlagGroup != nil {
|
||||
groups = append(groups, f.RepoFlagGroup)
|
||||
}
|
||||
return groups
|
||||
return lo.Filter(*f, func(group FlagGroup, _ int) bool {
|
||||
return group != nil && group.Name() != "Global"
|
||||
})
|
||||
}
|
||||
|
||||
func (f *Flags) AddFlags(cmd *cobra.Command) {
|
||||
@@ -715,141 +646,18 @@ func (f *Flags) Bind(cmd *cobra.Command) error {
|
||||
|
||||
// nolint: gocyclo
|
||||
func (f *Flags) ToOptions(args []string) (Options, error) {
|
||||
var err error
|
||||
opts := Options{
|
||||
AppVersion: app.Version(),
|
||||
args: args,
|
||||
}
|
||||
|
||||
if f.GlobalFlagGroup != nil {
|
||||
opts.GlobalOptions, err = f.GlobalFlagGroup.ToOptions()
|
||||
if err != nil {
|
||||
return Options{}, xerrors.Errorf("global flag error: %w", err)
|
||||
for _, group := range *f { // Include global flags
|
||||
if err := parseFlags(group); err != nil {
|
||||
return Options{}, xerrors.Errorf("unable to parse flags: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
if f.AWSFlagGroup != nil {
|
||||
opts.AWSOptions, err = f.AWSFlagGroup.ToOptions()
|
||||
if err != nil {
|
||||
return Options{}, xerrors.Errorf("aws flag error: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
if f.CacheFlagGroup != nil {
|
||||
opts.CacheOptions, err = f.CacheFlagGroup.ToOptions()
|
||||
if err != nil {
|
||||
return Options{}, xerrors.Errorf("cache flag error: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
if f.CleanFlagGroup != nil {
|
||||
opts.CleanOptions, err = f.CleanFlagGroup.ToOptions()
|
||||
if err != nil {
|
||||
return Options{}, xerrors.Errorf("clean flag error: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
if f.DBFlagGroup != nil {
|
||||
opts.DBOptions, err = f.DBFlagGroup.ToOptions()
|
||||
if err != nil {
|
||||
return Options{}, xerrors.Errorf("db flag error: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
if f.ImageFlagGroup != nil {
|
||||
opts.ImageOptions, err = f.ImageFlagGroup.ToOptions()
|
||||
if err != nil {
|
||||
return Options{}, xerrors.Errorf("image flag error: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
if f.K8sFlagGroup != nil {
|
||||
opts.K8sOptions, err = f.K8sFlagGroup.ToOptions()
|
||||
if err != nil {
|
||||
return Options{}, xerrors.Errorf("k8s flag error: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
if f.LicenseFlagGroup != nil {
|
||||
opts.LicenseOptions, err = f.LicenseFlagGroup.ToOptions()
|
||||
if err != nil {
|
||||
return Options{}, xerrors.Errorf("license flag error: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
if f.MisconfFlagGroup != nil {
|
||||
opts.MisconfOptions, err = f.MisconfFlagGroup.ToOptions()
|
||||
if err != nil {
|
||||
return Options{}, xerrors.Errorf("misconfiguration flag error: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
if f.ModuleFlagGroup != nil {
|
||||
opts.ModuleOptions, err = f.ModuleFlagGroup.ToOptions()
|
||||
if err != nil {
|
||||
return Options{}, xerrors.Errorf("module flag error: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
if f.PackageFlagGroup != nil {
|
||||
opts.PackageOptions, err = f.PackageFlagGroup.ToOptions()
|
||||
if err != nil {
|
||||
return Options{}, xerrors.Errorf("package flag error: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
if f.RegoFlagGroup != nil {
|
||||
opts.RegoOptions, err = f.RegoFlagGroup.ToOptions()
|
||||
if err != nil {
|
||||
return Options{}, xerrors.Errorf("rego flag error: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
if f.RemoteFlagGroup != nil {
|
||||
opts.RemoteOptions, err = f.RemoteFlagGroup.ToOptions()
|
||||
if err != nil {
|
||||
return Options{}, xerrors.Errorf("remote flag error: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
if f.RegistryFlagGroup != nil {
|
||||
opts.RegistryOptions, err = f.RegistryFlagGroup.ToOptions()
|
||||
if err != nil {
|
||||
return Options{}, xerrors.Errorf("registry flag error: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
if f.RepoFlagGroup != nil {
|
||||
opts.RepoOptions, err = f.RepoFlagGroup.ToOptions()
|
||||
if err != nil {
|
||||
return Options{}, xerrors.Errorf("repo flag error: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
if f.ReportFlagGroup != nil {
|
||||
opts.ReportOptions, err = f.ReportFlagGroup.ToOptions()
|
||||
if err != nil {
|
||||
return Options{}, xerrors.Errorf("report flag error: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
if f.ScanFlagGroup != nil {
|
||||
opts.ScanOptions, err = f.ScanFlagGroup.ToOptions(args)
|
||||
if err != nil {
|
||||
return Options{}, xerrors.Errorf("scan flag error: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
if f.SecretFlagGroup != nil {
|
||||
opts.SecretOptions, err = f.SecretFlagGroup.ToOptions()
|
||||
if err != nil {
|
||||
return Options{}, xerrors.Errorf("secret flag error: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
if f.VulnerabilityFlagGroup != nil {
|
||||
opts.VulnerabilityOptions, err = f.VulnerabilityFlagGroup.ToOptions()
|
||||
if err != nil {
|
||||
return Options{}, xerrors.Errorf("vulnerability flag error: %w", err)
|
||||
if err := group.ToOptions(&opts); err != nil {
|
||||
return Options{}, xerrors.Errorf("unable to convert flags to options: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -935,3 +743,16 @@ func HiddenFlags() []string {
|
||||
}
|
||||
return hiddenFlags
|
||||
}
|
||||
|
||||
// findFlagGroup finds a flag group by type T
|
||||
// Note that Go generics doesn't support methods today.
|
||||
// cf. https://github.com/golang/go/issues/49085
|
||||
func findFlagGroup[T FlagGroup](f *Flags) (T, bool) {
|
||||
for _, group := range *f {
|
||||
if g, ok := group.(T); ok {
|
||||
return g, true
|
||||
}
|
||||
}
|
||||
var zero T
|
||||
return zero, false
|
||||
}
|
||||
|
||||
@@ -69,23 +69,20 @@ func (f *PackageFlagGroup) Flags() []Flagger {
|
||||
}
|
||||
}
|
||||
|
||||
func (f *PackageFlagGroup) ToOptions() (PackageOptions, error) {
|
||||
if err := parseFlags(f); err != nil {
|
||||
return PackageOptions{}, err
|
||||
}
|
||||
|
||||
func (f *PackageFlagGroup) ToOptions(opts *Options) error {
|
||||
var relationships []ftypes.Relationship
|
||||
for _, r := range f.PkgRelationships.Value() {
|
||||
relationship, err := ftypes.NewRelationship(r)
|
||||
if err != nil {
|
||||
return PackageOptions{}, err
|
||||
return err
|
||||
}
|
||||
relationships = append(relationships, relationship)
|
||||
}
|
||||
|
||||
return PackageOptions{
|
||||
opts.PackageOptions = PackageOptions{
|
||||
IncludeDevDeps: f.IncludeDevDeps.Value(),
|
||||
PkgTypes: f.PkgTypes.Value(),
|
||||
PkgRelationships: relationships,
|
||||
}, nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -76,9 +76,10 @@ func TestPackageFlagGroup_ToOptions(t *testing.T) {
|
||||
PkgRelationships: flag.PkgRelationshipsFlag.Clone(),
|
||||
}
|
||||
|
||||
got, err := f.ToOptions()
|
||||
flags := flag.Flags{f}
|
||||
got, err := flags.ToOptions(nil)
|
||||
require.NoError(t, err)
|
||||
assert.EqualExportedValuesf(t, tt.want, got, "PackageFlagGroup")
|
||||
assert.EqualExportedValues(t, tt.want, got.PackageOptions)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,27 +75,23 @@ func (f *RegistryFlagGroup) Flags() []Flagger {
|
||||
}
|
||||
}
|
||||
|
||||
func (f *RegistryFlagGroup) ToOptions() (RegistryOptions, error) {
|
||||
if err := parseFlags(f); err != nil {
|
||||
return RegistryOptions{}, err
|
||||
}
|
||||
|
||||
func (f *RegistryFlagGroup) ToOptions(opts *Options) error {
|
||||
var credentials []types.Credential
|
||||
users := f.Username.Value()
|
||||
passwords := f.Password.Value()
|
||||
if f.PasswordStdin.Value() {
|
||||
if len(passwords) != 0 {
|
||||
return RegistryOptions{}, xerrors.New("'--password' and '--password-stdin' can't be used at the same time")
|
||||
return xerrors.New("'--password' and '--password-stdin' can't be used at the same time")
|
||||
}
|
||||
contents, err := io.ReadAll(os.Stdin)
|
||||
if err != nil {
|
||||
return RegistryOptions{}, xerrors.Errorf("failed to read from stdin: %w", err)
|
||||
return xerrors.Errorf("failed to read from stdin: %w", err)
|
||||
}
|
||||
// "--password-stdin" doesn't support comma-separated passwords
|
||||
passwords = []string{strings.TrimRight(string(contents), "\r\n")}
|
||||
}
|
||||
if len(users) != len(passwords) {
|
||||
return RegistryOptions{}, xerrors.New("the number of usernames and passwords must match")
|
||||
return xerrors.New("the number of usernames and passwords must match")
|
||||
}
|
||||
for i, user := range users {
|
||||
credentials = append(credentials, types.Credential{
|
||||
@@ -104,9 +100,10 @@ func (f *RegistryFlagGroup) ToOptions() (RegistryOptions, error) {
|
||||
})
|
||||
}
|
||||
|
||||
return RegistryOptions{
|
||||
opts.RegistryOptions = RegistryOptions{
|
||||
Credentials: credentials,
|
||||
RegistryToken: f.RegistryToken.Value(),
|
||||
RegistryMirrors: f.RegistryMirrors.Value(),
|
||||
}, nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -102,17 +102,14 @@ func (f *RegoFlagGroup) Flags() []Flagger {
|
||||
}
|
||||
}
|
||||
|
||||
func (f *RegoFlagGroup) ToOptions() (RegoOptions, error) {
|
||||
if err := parseFlags(f); err != nil {
|
||||
return RegoOptions{}, err
|
||||
}
|
||||
|
||||
return RegoOptions{
|
||||
func (f *RegoFlagGroup) ToOptions(opts *Options) error {
|
||||
opts.RegoOptions = RegoOptions{
|
||||
IncludeDeprecatedChecks: f.IncludeDeprecatedChecks.Value(),
|
||||
SkipCheckUpdate: f.SkipCheckUpdate.Value(),
|
||||
Trace: f.Trace.Value(),
|
||||
CheckPaths: f.CheckPaths.Value(),
|
||||
DataPaths: f.DataPaths.Value(),
|
||||
CheckNamespaces: f.CheckNamespaces.Value(),
|
||||
}, nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -110,11 +110,7 @@ func (f *RemoteFlagGroup) Flags() []Flagger {
|
||||
}
|
||||
}
|
||||
|
||||
func (f *RemoteFlagGroup) ToOptions() (RemoteOptions, error) {
|
||||
if err := parseFlags(f); err != nil {
|
||||
return RemoteOptions{}, err
|
||||
}
|
||||
|
||||
func (f *RemoteFlagGroup) ToOptions(opts *Options) error {
|
||||
serverAddr := f.ServerAddr.Value()
|
||||
customHeaders := splitCustomHeaders(f.CustomHeaders.Value())
|
||||
listen := f.Listen.Value()
|
||||
@@ -140,14 +136,15 @@ func (f *RemoteFlagGroup) ToOptions() (RemoteOptions, error) {
|
||||
customHeaders.Set(tokenHeader, token)
|
||||
}
|
||||
|
||||
return RemoteOptions{
|
||||
opts.RemoteOptions = RemoteOptions{
|
||||
Token: token,
|
||||
TokenHeader: tokenHeader,
|
||||
PathPrefix: f.PathPrefix.Value(),
|
||||
ServerAddr: serverAddr,
|
||||
CustomHeaders: customHeaders,
|
||||
Listen: listen,
|
||||
}, nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func splitCustomHeaders(headers []string) http.Header {
|
||||
|
||||
@@ -110,9 +110,10 @@ func TestRemoteFlagGroup_ToOptions(t *testing.T) {
|
||||
Token: flag.ServerTokenFlag.Clone(),
|
||||
TokenHeader: flag.ServerTokenHeaderFlag.Clone(),
|
||||
}
|
||||
got, err := f.ToOptions()
|
||||
flags := flag.Flags{f}
|
||||
got, err := flags.ToOptions(nil)
|
||||
require.NoError(t, err)
|
||||
assert.Equalf(t, tt.want, got, "ToOptions()")
|
||||
assert.Equal(t, tt.want, got.RemoteOptions)
|
||||
|
||||
// Assert log messages
|
||||
assert.Equal(t, tt.wantLogs, out.Messages(), tt.name)
|
||||
|
||||
@@ -50,14 +50,11 @@ func (f *RepoFlagGroup) Flags() []Flagger {
|
||||
}
|
||||
}
|
||||
|
||||
func (f *RepoFlagGroup) ToOptions() (RepoOptions, error) {
|
||||
if err := parseFlags(f); err != nil {
|
||||
return RepoOptions{}, err
|
||||
}
|
||||
|
||||
return RepoOptions{
|
||||
func (f *RepoFlagGroup) ToOptions(opts *Options) error {
|
||||
opts.RepoOptions = RepoOptions{
|
||||
RepoBranch: f.Branch.Value(),
|
||||
RepoCommit: f.Commit.Value(),
|
||||
RepoTag: f.Tag.Value(),
|
||||
}, nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -200,11 +200,7 @@ func (f *ReportFlagGroup) Flags() []Flagger {
|
||||
}
|
||||
}
|
||||
|
||||
func (f *ReportFlagGroup) ToOptions() (ReportOptions, error) {
|
||||
if err := parseFlags(f); err != nil {
|
||||
return ReportOptions{}, err
|
||||
}
|
||||
|
||||
func (f *ReportFlagGroup) ToOptions(opts *Options) error {
|
||||
format := types.Format(f.Format.Value())
|
||||
template := f.Template.Value()
|
||||
dependencyTree := f.DependencyTree.Value()
|
||||
@@ -241,27 +237,27 @@ func (f *ReportFlagGroup) ToOptions() (ReportOptions, error) {
|
||||
|
||||
// "--table-mode" option is available only with "--format table".
|
||||
if viper.IsSet(TableModeFlag.ConfigName) && format != types.FormatTable {
|
||||
return ReportOptions{}, xerrors.New(`"--table-mode" can be used only with "--format table".`)
|
||||
return xerrors.New(`"--table-mode" can be used only with "--format table".`)
|
||||
}
|
||||
|
||||
cs, err := loadComplianceTypes(f.Compliance.Value())
|
||||
if err != nil {
|
||||
return ReportOptions{}, xerrors.Errorf("unable to load compliance spec: %w", err)
|
||||
return xerrors.Errorf("unable to load compliance spec: %w", err)
|
||||
}
|
||||
|
||||
var outputPluginArgs []string
|
||||
if arg := f.OutputPluginArg.Value(); arg != "" {
|
||||
outputPluginArgs, err = shellwords.Parse(arg)
|
||||
if err != nil {
|
||||
return ReportOptions{}, xerrors.Errorf("unable to parse output plugin argument: %w", err)
|
||||
return xerrors.Errorf("unable to parse output plugin argument: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
if viper.IsSet(f.IgnoreFile.ConfigName) && !fsutils.FileExists(f.IgnoreFile.Value()) {
|
||||
return ReportOptions{}, xerrors.Errorf("ignore file not found: %s", f.IgnoreFile.Value())
|
||||
return xerrors.Errorf("ignore file not found: %s", f.IgnoreFile.Value())
|
||||
}
|
||||
|
||||
return ReportOptions{
|
||||
opts.ReportOptions = ReportOptions{
|
||||
Format: format,
|
||||
ReportFormat: f.ReportFormat.Value(),
|
||||
Template: template,
|
||||
@@ -277,7 +273,8 @@ func (f *ReportFlagGroup) ToOptions() (ReportOptions, error) {
|
||||
Compliance: cs,
|
||||
ShowSuppressed: f.ShowSuppressed.Value(),
|
||||
TableModes: xstrings.ToTSlice[types.TableMode](tableModes),
|
||||
}, nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func loadComplianceTypes(compliance string) (spec.ComplianceSpec, error) {
|
||||
|
||||
@@ -214,13 +214,14 @@ func TestReportFlagGroup_ToOptions(t *testing.T) {
|
||||
TableMode: flag.TableModeFlag.Clone(),
|
||||
}
|
||||
|
||||
got, err := f.ToOptions()
|
||||
flags := flag.Flags{f}
|
||||
got, err := flags.ToOptions(nil)
|
||||
if tt.wantErr != "" {
|
||||
require.Contains(t, err.Error(), tt.wantErr)
|
||||
require.ErrorContains(t, err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
|
||||
assert.EqualExportedValuesf(t, tt.want, got, "ToOptions()")
|
||||
assert.EqualExportedValues(t, tt.want, got.ReportOptions)
|
||||
|
||||
// Assert log messages
|
||||
assert.Equal(t, tt.wantLogs, out.Messages(), tt.name)
|
||||
@@ -235,7 +236,8 @@ func TestReportFlagGroup_ToOptions(t *testing.T) {
|
||||
IgnoreFile: flag.IgnoreFileFlag.Clone(),
|
||||
}
|
||||
|
||||
_, err := f.ToOptions()
|
||||
flags := flag.Flags{f}
|
||||
_, err := flags.ToOptions(nil)
|
||||
assert.ErrorContains(t, err, "ignore file not found: doesntexist")
|
||||
})
|
||||
}
|
||||
|
||||
@@ -184,14 +184,10 @@ func (f *ScanFlagGroup) Flags() []Flagger {
|
||||
}
|
||||
}
|
||||
|
||||
func (f *ScanFlagGroup) ToOptions(args []string) (ScanOptions, error) {
|
||||
if err := parseFlags(f); err != nil {
|
||||
return ScanOptions{}, err
|
||||
}
|
||||
|
||||
func (f *ScanFlagGroup) ToOptions(opts *Options) error {
|
||||
var target string
|
||||
if len(args) == 1 {
|
||||
target = args[0]
|
||||
if len(opts.args) == 1 {
|
||||
target = opts.args[0]
|
||||
}
|
||||
|
||||
parallel := f.Parallel.Value()
|
||||
@@ -204,7 +200,7 @@ func (f *ScanFlagGroup) ToOptions(args []string) (ScanOptions, error) {
|
||||
if f.DistroFlag != nil && f.DistroFlag.Value() != "" {
|
||||
family, version, _ := strings.Cut(f.DistroFlag.Value(), "/")
|
||||
if !slices.Contains(ftypes.OSTypes, ftypes.OSType(family)) {
|
||||
return ScanOptions{}, xerrors.Errorf("unknown OS family: %s, must be %q", family, ftypes.OSTypes)
|
||||
return xerrors.Errorf("unknown OS family: %s, must be %q", family, ftypes.OSTypes)
|
||||
}
|
||||
distro = ftypes.OS{
|
||||
Family: ftypes.OSType(family),
|
||||
@@ -212,7 +208,7 @@ func (f *ScanFlagGroup) ToOptions(args []string) (ScanOptions, error) {
|
||||
}
|
||||
}
|
||||
|
||||
return ScanOptions{
|
||||
opts.ScanOptions = ScanOptions{
|
||||
Target: target,
|
||||
SkipDirs: f.SkipDirs.Value(),
|
||||
SkipFiles: f.SkipFiles.Value(),
|
||||
@@ -224,5 +220,6 @@ func (f *ScanFlagGroup) ToOptions(args []string) (ScanOptions, error) {
|
||||
RekorURL: f.RekorURL.Value(),
|
||||
DetectionPriority: ftypes.DetectionPriority(f.DetectionPriority.Value()),
|
||||
Distro: distro,
|
||||
}, nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -147,9 +147,10 @@ func TestScanFlagGroup_ToOptions(t *testing.T) {
|
||||
DistroFlag: flag.DistroFlag.Clone(),
|
||||
}
|
||||
|
||||
got, err := f.ToOptions(tt.args)
|
||||
flags := flag.Flags{f}
|
||||
got, err := flags.ToOptions(tt.args)
|
||||
tt.assertion(t, err)
|
||||
assert.Equalf(t, tt.want, got, "ToOptions()")
|
||||
assert.Equal(t, tt.want, got.ScanOptions)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,12 +31,9 @@ func (f *SecretFlagGroup) Flags() []Flagger {
|
||||
return []Flagger{f.SecretConfig}
|
||||
}
|
||||
|
||||
func (f *SecretFlagGroup) ToOptions() (SecretOptions, error) {
|
||||
if err := parseFlags(f); err != nil {
|
||||
return SecretOptions{}, err
|
||||
}
|
||||
|
||||
return SecretOptions{
|
||||
func (f *SecretFlagGroup) ToOptions(opts *Options) error {
|
||||
opts.SecretOptions = SecretOptions{
|
||||
SecretConfigPath: f.SecretConfig.Value(),
|
||||
}, nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -82,11 +82,7 @@ func (f *VulnerabilityFlagGroup) Flags() []Flagger {
|
||||
}
|
||||
}
|
||||
|
||||
func (f *VulnerabilityFlagGroup) ToOptions() (VulnerabilityOptions, error) {
|
||||
if err := parseFlags(f); err != nil {
|
||||
return VulnerabilityOptions{}, err
|
||||
}
|
||||
|
||||
func (f *VulnerabilityFlagGroup) ToOptions(opts *Options) error {
|
||||
// Just convert string to dbTypes.Status as the validated values are passed here.
|
||||
ignoreStatuses := lo.Map(f.IgnoreStatus.Value(), func(s string, _ int) dbTypes.Status {
|
||||
return dbTypes.NewStatus(s)
|
||||
@@ -110,12 +106,13 @@ func (f *VulnerabilityFlagGroup) ToOptions() (VulnerabilityOptions, error) {
|
||||
}
|
||||
log.Debug("Ignore statuses", log.Any("statuses", ignoreStatuses))
|
||||
|
||||
return VulnerabilityOptions{
|
||||
opts.VulnerabilityOptions = VulnerabilityOptions{
|
||||
IgnoreStatuses: ignoreStatuses,
|
||||
VEXSources: lo.Map(f.VEX.Value(), func(s string, _ int) vex.Source {
|
||||
return vex.NewSource(s)
|
||||
}),
|
||||
SkipVEXRepoUpdate: f.SkipVEXRepoUpdate.Value(),
|
||||
VulnSeveritySources: xstrings.ToTSlice[dbTypes.SourceID](f.VulnSeveritySource.Value()),
|
||||
}, nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user