mirror of
https://github.com/anchore/syft.git
synced 2025-11-18 17:03:17 +01:00
simplify command alias logic + remove deprecation warning for root command
Signed-off-by: Alex Goodman <alex.goodman@anchore.com>
This commit is contained in:
parent
36e4af1953
commit
46636ccb3c
@ -22,6 +22,9 @@ If you encounter an issue, please [let us know using the issue tracker](https://
|
|||||||
To generate an SBOM for a Docker or OCI image:
|
To generate an SBOM for a Docker or OCI image:
|
||||||
```
|
```
|
||||||
syft packages <image>
|
syft packages <image>
|
||||||
|
|
||||||
|
# note: this is the same as not providing the "packages" subcommand
|
||||||
|
syft <image>
|
||||||
```
|
```
|
||||||
|
|
||||||
The above output includes only software that is visible in the container (i.e., the squashed representation of the image).
|
The above output includes only software that is visible in the container (i.e., the squashed representation of the image).
|
||||||
|
|||||||
38
cmd/cmd.go
38
cmd/cmd.go
@ -3,7 +3,6 @@ package cmd
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
@ -33,10 +32,6 @@ func init() {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// provided to disambiguate the root vs packages command, whichever is indicated by the cli args will be set here.
|
|
||||||
// TODO: when the root alias command is removed, this variable can be removed
|
|
||||||
var activeCmd *cobra.Command
|
|
||||||
|
|
||||||
func Execute() {
|
func Execute() {
|
||||||
if err := rootCmd.Execute(); err != nil {
|
if err := rootCmd.Execute(); err != nil {
|
||||||
fmt.Fprintln(os.Stderr, color.Red.Sprint(err.Error()))
|
fmt.Fprintln(os.Stderr, color.Red.Sprint(err.Error()))
|
||||||
@ -48,30 +43,9 @@ func Execute() {
|
|||||||
// be done without determining what the primary command that the config options should be bound to since there are
|
// be done without determining what the primary command that the config options should be bound to since there are
|
||||||
// shared concerns (the root-packages alias).
|
// shared concerns (the root-packages alias).
|
||||||
func initCmdAliasBindings() {
|
func initCmdAliasBindings() {
|
||||||
// TODO: when the root alias command is removed, this function (hack) can be removed
|
activeCmd, _, err := rootCmd.Find(os.Args[1:])
|
||||||
|
if err != nil {
|
||||||
// map of all commands except for root
|
panic(err)
|
||||||
commands := make(map[string]*cobra.Command)
|
|
||||||
for _, c := range rootCmd.Commands() {
|
|
||||||
name := strings.Split(c.Use, " ")[0]
|
|
||||||
commands[name] = c
|
|
||||||
}
|
|
||||||
|
|
||||||
activeCmd = rootCmd
|
|
||||||
for i, a := range os.Args {
|
|
||||||
if i == 0 {
|
|
||||||
// don't consider the bin
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
// check to see if this argument may be a command
|
|
||||||
if c, exists := commands[a]; exists {
|
|
||||||
activeCmd = c
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if activeCmd == rootCmd {
|
|
||||||
// note: cobra supports command deprecation, however the command name is empty and does not report to stderr
|
|
||||||
fmt.Fprintln(os.Stderr, color.New(color.Bold, color.Red).Sprintf("The root command is deprecated, please use the 'packages' subcommand"))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if activeCmd == packagesCmd || activeCmd == rootCmd {
|
if activeCmd == packagesCmd || activeCmd == rootCmd {
|
||||||
@ -81,11 +55,13 @@ func initCmdAliasBindings() {
|
|||||||
// reading the application configuration, which implies that it must be an initializer (or rewrite the command
|
// reading the application configuration, which implies that it must be an initializer (or rewrite the command
|
||||||
// initialization structure against typical patterns used with cobra, which is somewhat extreme for a
|
// initialization structure against typical patterns used with cobra, which is somewhat extreme for a
|
||||||
// temporary alias)
|
// temporary alias)
|
||||||
if err := bindConfigOptions(activeCmd.Flags()); err != nil {
|
if err = bindPackagesConfigOptions(activeCmd.Flags()); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if err := bindConfigOptions(packagesCmd.Flags()); err != nil {
|
// even though the root command or packages command is NOT being run, we still need default bindings
|
||||||
|
// such that application config parsing passes.
|
||||||
|
if err = bindPackagesConfigOptions(packagesCmd.Flags()); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -138,7 +138,7 @@ func setPackageFlags(flags *pflag.FlagSet) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func bindConfigOptions(flags *pflag.FlagSet) error {
|
func bindPackagesConfigOptions(flags *pflag.FlagSet) error {
|
||||||
///////// Formatting & Input options //////////////////////////////////////////////
|
///////// Formatting & Input options //////////////////////////////////////////////
|
||||||
|
|
||||||
if err := viper.BindPFlag("package.cataloger.scope", flags.Lookup("scope")); err != nil {
|
if err := viper.BindPFlag("package.cataloger.scope", flags.Lookup("scope")); err != nil {
|
||||||
|
|||||||
@ -9,18 +9,41 @@ import (
|
|||||||
|
|
||||||
func TestRootCmdAliasesToPackagesSubcommand(t *testing.T) {
|
func TestRootCmdAliasesToPackagesSubcommand(t *testing.T) {
|
||||||
request := "docker-archive:" + getFixtureImage(t, "image-pkg-coverage")
|
request := "docker-archive:" + getFixtureImage(t, "image-pkg-coverage")
|
||||||
deprecationWarning := "The root command is deprecated"
|
|
||||||
|
|
||||||
_, aliasStdout, aliasStderr := runSyftCommand(t, nil, request)
|
tests := []struct {
|
||||||
|
name string
|
||||||
if !strings.Contains(aliasStderr, deprecationWarning) {
|
env map[string]string
|
||||||
t.Errorf("missing root-packages alias deprecation warning")
|
assertions []traitAssertion
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "go-case",
|
||||||
|
assertions: []traitAssertion{
|
||||||
|
assertTableReport,
|
||||||
|
assertSuccessfulReturnCode,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "respond-to-output-binding",
|
||||||
|
env: map[string]string{
|
||||||
|
"SYFT_OUTPUT": "text",
|
||||||
|
},
|
||||||
|
assertions: []traitAssertion{
|
||||||
|
assertInOutput("[Image]"),
|
||||||
|
assertSuccessfulReturnCode,
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
_, pkgsStdout, pkgsStderr := runSyftCommand(t, nil, "packages", request)
|
for _, test := range tests {
|
||||||
|
t.Run(test.name, func(t *testing.T) {
|
||||||
|
aliasCmd, aliasStdout, aliasStderr := runSyftCommand(t, test.env, request)
|
||||||
|
for _, traitFn := range test.assertions {
|
||||||
|
traitFn(t, aliasStdout, aliasStderr, aliasCmd.ProcessState.ExitCode())
|
||||||
|
}
|
||||||
|
|
||||||
if strings.Contains(pkgsStderr, deprecationWarning) {
|
pkgCmd, pkgsStdout, pkgsStderr := runSyftCommand(t, test.env, "packages", request)
|
||||||
t.Errorf("packages command should not have deprecation warning")
|
for _, traitFn := range test.assertions {
|
||||||
|
traitFn(t, pkgsStdout, pkgsStderr, pkgCmd.ProcessState.ExitCode())
|
||||||
}
|
}
|
||||||
|
|
||||||
if aliasStdout != pkgsStdout {
|
if aliasStdout != pkgsStdout {
|
||||||
@ -29,6 +52,8 @@ func TestRootCmdAliasesToPackagesSubcommand(t *testing.T) {
|
|||||||
diffs := dmp.DiffMain(aliasStdout, pkgsStdout, true)
|
diffs := dmp.DiffMain(aliasStdout, pkgsStdout, true)
|
||||||
t.Error(dmp.DiffPrettyText(diffs))
|
t.Error(dmp.DiffPrettyText(diffs))
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPersistentFlags(t *testing.T) {
|
func TestPersistentFlags(t *testing.T) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user