fix: allow the latest tag (#864)

* fix: allow the latest tag

* docs: update README
This commit is contained in:
Teppei Fukuda
2021-02-25 16:23:11 +02:00
committed by GitHub
parent 425eaf8a2a
commit fcb9a93d05
10 changed files with 7 additions and 157 deletions

View File

@@ -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.**

View File

@@ -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
}

View File

@@ -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

View File

@@ -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)
}

View File

@@ -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)
}

View File

@@ -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)
}

View File

@@ -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
}

View File

@@ -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) {

View File

@@ -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
}

View File

@@ -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)
}
})
}
}