mirror of
https://github.com/aquasecurity/trivy.git
synced 2025-12-12 07:40:48 -08:00
fix: allow the latest tag (#864)
* fix: allow the latest tag * docs: update README
This commit is contained in:
@@ -234,7 +234,7 @@ $ go install
|
||||
|
||||
## Image
|
||||
|
||||
Simply specify an image name (and a tag). **The `latest` tag should be avoided as problems occur with the image cache.** See [Clear caches](#clear-caches).
|
||||
Simply specify an image name (and a tag).
|
||||
|
||||
### Basic
|
||||
|
||||
@@ -1405,7 +1405,7 @@ $ trivy server --cache-backend redis://localhost:6379
|
||||
|
||||
### Clear caches
|
||||
|
||||
The `--clear-cache` option removes caches. This option is useful if the image which has the same tag is updated (such as when using `latest` tag).
|
||||
The `--clear-cache` option removes caches.
|
||||
|
||||
**The scan is not performed.**
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ func New(c *cli.Context) (Config, error) {
|
||||
}
|
||||
|
||||
// Init initializes the artifact config
|
||||
func (c *Config) Init(image bool) error {
|
||||
func (c *Config) Init() error {
|
||||
if c.onlyUpdate != "" || c.refresh || c.autoRefresh {
|
||||
c.Logger.Warn("--only-update, --refresh and --auto-refresh are unnecessary and ignored now. These commands will be removed in the next version.")
|
||||
}
|
||||
@@ -64,12 +64,6 @@ func (c *Config) Init(image bool) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if image {
|
||||
if err := c.ImageConfig.Init(c.Context.Args(), c.Logger); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -152,25 +152,6 @@ func TestConfig_Init(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "with latest tag",
|
||||
args: []string{"--auto-refresh", "gcr.io/distroless/base"},
|
||||
logs: []string{
|
||||
"--only-update, --refresh and --auto-refresh are unnecessary and ignored now. These commands will be removed in the next version.",
|
||||
"You should avoid using the :latest tag as it is cached. You need to specify '--clear-cache' option when :latest image is changed",
|
||||
},
|
||||
want: Config{
|
||||
ReportConfig: config.ReportConfig{
|
||||
Severities: []dbTypes.Severity{dbTypes.SeverityCritical},
|
||||
Output: os.Stdout,
|
||||
VulnType: []string{"os", "library"},
|
||||
},
|
||||
ArtifactConfig: config.ArtifactConfig{
|
||||
Target: "gcr.io/distroless/base",
|
||||
},
|
||||
autoRefresh: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "sad: skip and download db",
|
||||
args: []string{"--skip-update", "--download-db-only", "alpine:3.10"},
|
||||
@@ -184,11 +165,6 @@ func TestConfig_Init(t *testing.T) {
|
||||
},
|
||||
wantErr: "arguments error",
|
||||
},
|
||||
{
|
||||
name: "sad: invalid image name",
|
||||
args: []string{`!"#$%&'()`},
|
||||
wantErr: "could not parse reference",
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
@@ -216,7 +192,7 @@ func TestConfig_Init(t *testing.T) {
|
||||
require.NoError(t, err, err)
|
||||
|
||||
c.GlobalConfig.Logger = logger.Sugar()
|
||||
err = c.Init(true)
|
||||
err = c.Init()
|
||||
|
||||
// tests log messages
|
||||
var gotMessages []string
|
||||
|
||||
@@ -30,7 +30,7 @@ func FilesystemRun(cliCtx *cli.Context) error {
|
||||
}
|
||||
|
||||
// initialize config
|
||||
if err = c.Init(false); err != nil {
|
||||
if err = c.Init(); err != nil {
|
||||
return xerrors.Errorf("failed to initialize options: %w", err)
|
||||
}
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ func ImageRun(cliCtx *cli.Context) error {
|
||||
}
|
||||
|
||||
// initialize config
|
||||
if err := c.Init(true); err != nil {
|
||||
if err := c.Init(); err != nil {
|
||||
return xerrors.Errorf("failed to initialize options: %w", err)
|
||||
}
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ func RepositoryRun(cliCtx *cli.Context) error {
|
||||
}
|
||||
|
||||
// initialize config
|
||||
if err = c.Init(false); err != nil {
|
||||
if err = c.Init(); err != nil {
|
||||
return xerrors.Errorf("failed to initialize options: %w", err)
|
||||
}
|
||||
|
||||
|
||||
@@ -67,10 +67,6 @@ func (c *Config) Init() (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := c.ImageConfig.Init(c.Context.Args(), c.Logger); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -198,24 +198,6 @@ func TestConfig_Init(t *testing.T) {
|
||||
CustomHeaders: http.Header{},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "with latest tag",
|
||||
args: []string{"gcr.io/distroless/base"},
|
||||
logs: []string{
|
||||
"You should avoid using the :latest tag as it is cached. You need to specify '--clear-cache' option when :latest image is changed",
|
||||
},
|
||||
want: Config{
|
||||
ReportConfig: config.ReportConfig{
|
||||
Severities: []dbTypes.Severity{dbTypes.SeverityCritical},
|
||||
Output: os.Stdout,
|
||||
VulnType: []string{"os", "library"},
|
||||
},
|
||||
ArtifactConfig: config.ArtifactConfig{
|
||||
Target: "gcr.io/distroless/base",
|
||||
},
|
||||
CustomHeaders: http.Header{},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "sad: multiple image names",
|
||||
args: []string{"centos:7", "alpine:3.10"},
|
||||
@@ -224,11 +206,6 @@ func TestConfig_Init(t *testing.T) {
|
||||
},
|
||||
wantErr: "arguments error",
|
||||
},
|
||||
{
|
||||
name: "sad: invalid image name",
|
||||
args: []string{`!"#$%&'()`},
|
||||
wantErr: "could not parse reference",
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"github.com/google/go-containerregistry/pkg/name"
|
||||
"github.com/urfave/cli/v2"
|
||||
"go.uber.org/zap"
|
||||
"golang.org/x/xerrors"
|
||||
)
|
||||
|
||||
// ImageConfig holds the config for scanning images
|
||||
@@ -20,21 +17,3 @@ func NewImageConfig(c *cli.Context) ImageConfig {
|
||||
ListAllPkgs: c.Bool("list-all-pkgs"),
|
||||
}
|
||||
}
|
||||
|
||||
// Init initializes the imageConfig
|
||||
func (c *ImageConfig) Init(args cli.Args, logger *zap.SugaredLogger) (err error) {
|
||||
imageName := args.First()
|
||||
|
||||
// Check whether 'latest' tag is used
|
||||
if imageName != "" {
|
||||
ref, err := name.ParseReference(imageName)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("invalid image: %w", err)
|
||||
}
|
||||
if ref.Identifier() == "latest" {
|
||||
logger.Warn("You should avoid using the :latest tag as it is cached. You need to specify '--clear-cache' option when :latest image is changed")
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -1,72 +0,0 @@
|
||||
package config_test
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/urfave/cli/v2"
|
||||
"go.uber.org/zap"
|
||||
"go.uber.org/zap/zaptest/observer"
|
||||
|
||||
"github.com/aquasecurity/trivy/internal/config"
|
||||
)
|
||||
|
||||
func TestImageConfig_Init(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
args []string
|
||||
logs []string
|
||||
wantErr string
|
||||
}{
|
||||
{
|
||||
name: "happy path",
|
||||
args: []string{"alpine:3.10"},
|
||||
},
|
||||
{
|
||||
name: "with latest tag",
|
||||
args: []string{"gcr.io/distroless/base"},
|
||||
logs: []string{
|
||||
"You should avoid using the :latest tag as it is cached. You need to specify '--clear-cache' option when :latest image is changed",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "sad: invalid image name",
|
||||
args: []string{`!"#$%&'()`},
|
||||
wantErr: "could not parse reference",
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
core, obs := observer.New(zap.InfoLevel)
|
||||
logger := zap.New(core)
|
||||
|
||||
app := cli.NewApp()
|
||||
set := flag.NewFlagSet("test", 0)
|
||||
ctx := cli.NewContext(app, set, nil)
|
||||
_ = set.Parse(tt.args)
|
||||
|
||||
c := config.NewImageConfig(ctx)
|
||||
|
||||
err := c.Init(ctx.Args(), logger.Sugar())
|
||||
|
||||
// tests log messages
|
||||
var gotMessages []string
|
||||
for _, entry := range obs.AllUntimed() {
|
||||
gotMessages = append(gotMessages, entry.Message)
|
||||
}
|
||||
assert.Equal(t, tt.logs, gotMessages, tt.name)
|
||||
|
||||
// test the error
|
||||
switch {
|
||||
case tt.wantErr != "":
|
||||
require.NotNil(t, err)
|
||||
assert.Contains(t, err.Error(), tt.wantErr, tt.name)
|
||||
return
|
||||
default:
|
||||
assert.NoError(t, err, tt.name)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user