Skip to content

Commit

Permalink
ignore NVD data age + tests (#441)
Browse files Browse the repository at this point in the history
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
  • Loading branch information
wagoodman authored Nov 25, 2024
1 parent c5d02b6 commit 1f1c46b
Show file tree
Hide file tree
Showing 2 changed files with 108 additions and 9 deletions.
27 changes: 22 additions & 5 deletions cmd/grype-db/cli/commands/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,11 +108,16 @@ func runBuild(cfg buildConfig) error {
return fmt.Errorf("unable to get provider states: %w", err)
}

earliest, err := earliestTimestamp(states)
if err != nil {
return fmt.Errorf("unable to get earliest timestamp: %w", err)
}

return process.Build(process.BuildConfig{
SchemaVersion: cfg.SchemaVersion,
Directory: cfg.Directory,
States: states,
Timestamp: earliestTimestamp(states),
Timestamp: earliest,
IncludeCPEParts: cfg.IncludeCPEParts,
InferNVDFixVersions: cfg.InferNVDFixVersions,
})
Expand Down Expand Up @@ -148,18 +153,30 @@ func providerStates(skipValidation bool, providers []provider.Provider) ([]provi
return states, nil
}

func earliestTimestamp(states []provider.State) time.Time {
earliest := states[0].Timestamp
func earliestTimestamp(states []provider.State) (time.Time, error) {
if len(states) == 0 {
return time.Time{}, fmt.Errorf("cannot find earliest timestamp: no states provided")
}
var earliest time.Time
for _, s := range states {
// the NVD api is constantly down, so we don't want to consider it for the earliest timestamp
if s.Provider == "nvd" {
log.WithFields("provider", s.Provider).Trace("not considering data age for provider")
log.WithFields("provider", s.Provider).Debug("not considering data age for provider")
continue
}
if earliest.IsZero() {
earliest = s.Timestamp
continue
}
if s.Timestamp.Before(earliest) {
earliest = s.Timestamp
}
}

if earliest.IsZero() {
return time.Time{}, fmt.Errorf("unable to determine earliest timestamp")
}

log.WithFields("timestamp", earliest).Debug("earliest data timestamp")
return earliest
return earliest, nil
}
90 changes: 86 additions & 4 deletions cmd/grype-db/cli/commands/build_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,17 @@ import (
"testing"
"time"

"github.com/stretchr/testify/require"

"github.com/anchore/grype-db/pkg/provider"
)

func Test_earliestTimestamp(t *testing.T) {
tests := []struct {
name string
states []provider.State
want time.Time
name string
states []provider.State
want time.Time
wantErr require.ErrorAssertionFunc
}{
{
name: "happy path",
Expand All @@ -29,12 +32,91 @@ func Test_earliestTimestamp(t *testing.T) {
},
want: time.Date(2021, 1, 1, 0, 0, 0, 0, time.UTC),
},
{
name: "empty states",
states: []provider.State{},
want: time.Time{},
wantErr: requireErrorContains("cannot find earliest timestamp: no states provided"),
},
{
name: "single state",
states: []provider.State{
{
Timestamp: time.Date(2021, 1, 1, 0, 0, 0, 0, time.UTC),
},
},
want: time.Date(2021, 1, 1, 0, 0, 0, 0, time.UTC),
},
{
name: "all states have provider nvd",
states: []provider.State{
{
Provider: "nvd",
Timestamp: time.Date(2021, 1, 1, 0, 0, 0, 0, time.UTC),
},
{
Provider: "nvd",
Timestamp: time.Date(2021, 1, 2, 0, 0, 0, 0, time.UTC),
},
},
want: time.Time{},
wantErr: requireErrorContains("unable to determine earliest timestamp"),
},
{
name: "mix of nvd and non-nvd providers",
states: []provider.State{
{
Provider: "nvd",
Timestamp: time.Date(2021, 1, 1, 0, 0, 0, 0, time.UTC),
},
{
Provider: "other",
Timestamp: time.Date(2021, 1, 3, 0, 0, 0, 0, time.UTC),
},
{
Provider: "other",
Timestamp: time.Date(2021, 1, 2, 0, 0, 0, 0, time.UTC),
},
},
want: time.Date(2021, 1, 2, 0, 0, 0, 0, time.UTC),
},
{
name: "timestamps are the same",
states: []provider.State{
{
Timestamp: time.Date(2021, 1, 1, 0, 0, 0, 0, time.UTC),
},
{
Timestamp: time.Date(2021, 1, 1, 0, 0, 0, 0, time.UTC),
},
{
Timestamp: time.Date(2021, 1, 1, 0, 0, 0, 0, time.UTC),
},
},
want: time.Date(2021, 1, 1, 0, 0, 0, 0, time.UTC),
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := earliestTimestamp(tt.states); !reflect.DeepEqual(got, tt.want) {
if tt.wantErr == nil {
tt.wantErr = require.NoError
}
got, err := earliestTimestamp(tt.states)
tt.wantErr(t, err)
if err != nil {
return
}
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("earliestTimestamp() = %v, want %v", got, tt.want)
}
})
}
}

func requireErrorContains(text string) require.ErrorAssertionFunc {
return func(t require.TestingT, err error, msgAndArgs ...interface{}) {
require.Error(t, err, msgAndArgs...)
require.Contains(t, err.Error(), text, msgAndArgs...)
}
}

0 comments on commit 1f1c46b

Please sign in to comment.