mirror of
https://github.com/anchore/syft.git
synced 2026-02-12 02:26:42 +01:00
Deduplicate digests from user configuration (#2522)
* deduplicate digests from user configuration Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * backout pointer reciever change on imageSource Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> --------- Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
This commit is contained in:
parent
0bc31f4e27
commit
3eab5932e5
@ -2,6 +2,9 @@ package options
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"sort"
|
||||||
|
|
||||||
|
"github.com/scylladb/go-set/strset"
|
||||||
|
|
||||||
intFile "github.com/anchore/syft/internal/file"
|
intFile "github.com/anchore/syft/internal/file"
|
||||||
"github.com/anchore/syft/syft/file"
|
"github.com/anchore/syft/syft/file"
|
||||||
@ -35,6 +38,10 @@ func defaultFileConfig() fileConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *fileConfig) PostLoad() error {
|
func (c *fileConfig) PostLoad() error {
|
||||||
|
digests := strset.New(c.Metadata.Digests...).List()
|
||||||
|
sort.Strings(digests)
|
||||||
|
c.Metadata.Digests = digests
|
||||||
|
|
||||||
switch c.Metadata.Selection {
|
switch c.Metadata.Selection {
|
||||||
case file.NoFilesSelection, file.FilesOwnedByPackageSelection, file.AllFilesSelection:
|
case file.NoFilesSelection, file.FilesOwnedByPackageSelection, file.AllFilesSelection:
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
56
cmd/syft/cli/options/file_test.go
Normal file
56
cmd/syft/cli/options/file_test.go
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
package options
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
|
"github.com/anchore/syft/syft/file"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_fileConfig_PostLoad(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
cfg fileConfig
|
||||||
|
assert func(t *testing.T, cfg fileConfig)
|
||||||
|
wantErr assert.ErrorAssertionFunc
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "deduplicate digests",
|
||||||
|
cfg: fileConfig{
|
||||||
|
Metadata: fileMetadata{
|
||||||
|
Selection: file.NoFilesSelection,
|
||||||
|
Digests: []string{"sha1", "sha1"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
assert: func(t *testing.T, cfg fileConfig) {
|
||||||
|
assert.Equal(t, []string{"sha1"}, cfg.Metadata.Digests)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "error on invalid selection",
|
||||||
|
cfg: fileConfig{
|
||||||
|
Metadata: fileMetadata{
|
||||||
|
Selection: file.Selection("invalid"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
wantErr: assert.Error,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "error on empty selection",
|
||||||
|
cfg: fileConfig{},
|
||||||
|
wantErr: assert.Error,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
if tt.wantErr == nil {
|
||||||
|
tt.wantErr = assert.NoError
|
||||||
|
}
|
||||||
|
tt.wantErr(t, tt.cfg.PostLoad())
|
||||||
|
if tt.assert != nil {
|
||||||
|
tt.assert(t, tt.cfg)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -2,6 +2,7 @@ package options
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/scylladb/go-set/strset"
|
"github.com/scylladb/go-set/strset"
|
||||||
@ -34,6 +35,13 @@ func defaultSourceConfig() sourceConfig {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *fileSource) PostLoad() error {
|
||||||
|
digests := strset.New(c.Digests...).List()
|
||||||
|
sort.Strings(digests)
|
||||||
|
c.Digests = digests
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (c imageSource) PostLoad() error {
|
func (c imageSource) PostLoad() error {
|
||||||
return checkDefaultSourceValues(c.DefaultPullSource)
|
return checkDefaultSourceValues(c.DefaultPullSource)
|
||||||
}
|
}
|
||||||
|
|||||||
37
cmd/syft/cli/options/source_test.go
Normal file
37
cmd/syft/cli/options/source_test.go
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
package options
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_fileSource_PostLoad(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
cfg fileSource
|
||||||
|
assert func(t *testing.T, cfg fileSource)
|
||||||
|
wantErr assert.ErrorAssertionFunc
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "deduplicate digests",
|
||||||
|
cfg: fileSource{
|
||||||
|
Digests: []string{"sha1", "sha1"},
|
||||||
|
},
|
||||||
|
assert: func(t *testing.T, cfg fileSource) {
|
||||||
|
assert.Equal(t, []string{"sha1"}, cfg.Digests)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
if tt.wantErr == nil {
|
||||||
|
tt.wantErr = assert.NoError
|
||||||
|
}
|
||||||
|
tt.wantErr(t, tt.cfg.PostLoad())
|
||||||
|
if tt.assert != nil {
|
||||||
|
tt.assert(t, tt.cfg)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -22,6 +22,7 @@ func supportedHashAlgorithms() []crypto.Hash {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func NewDigestsFromFile(closer io.ReadCloser, hashes []crypto.Hash) ([]file.Digest, error) {
|
func NewDigestsFromFile(closer io.ReadCloser, hashes []crypto.Hash) ([]file.Digest, error) {
|
||||||
|
hashes = NormalizeHashes(hashes)
|
||||||
// create a set of hasher objects tied together with a single writer to feed content into
|
// create a set of hasher objects tied together with a single writer to feed content into
|
||||||
hashers := make([]hash.Hash, len(hashes))
|
hashers := make([]hash.Hash, len(hashes))
|
||||||
writers := make([]io.Writer, len(hashes))
|
writers := make([]io.Writer, len(hashes))
|
||||||
@ -67,7 +68,7 @@ func Hashers(names ...string) ([]crypto.Hash, error) {
|
|||||||
}
|
}
|
||||||
hashers = append(hashers, hashObj)
|
hashers = append(hashers, hashObj)
|
||||||
}
|
}
|
||||||
return hashers, nil
|
return NormalizeHashes(hashers), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func CleanDigestAlgorithmName(name string) string {
|
func CleanDigestAlgorithmName(name string) string {
|
||||||
|
|||||||
24
internal/file/normalize_hashes.go
Normal file
24
internal/file/normalize_hashes.go
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
package file
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto"
|
||||||
|
"sort"
|
||||||
|
|
||||||
|
"github.com/scylladb/go-set/uset"
|
||||||
|
)
|
||||||
|
|
||||||
|
func NormalizeHashes(hashes []crypto.Hash) []crypto.Hash {
|
||||||
|
set := uset.New()
|
||||||
|
for _, h := range hashes {
|
||||||
|
set.Add(uint(h))
|
||||||
|
}
|
||||||
|
list := set.List()
|
||||||
|
sort.Slice(list, func(i, j int) bool {
|
||||||
|
return list[i] < list[j]
|
||||||
|
})
|
||||||
|
result := make([]crypto.Hash, len(list))
|
||||||
|
for i, v := range list {
|
||||||
|
result[i] = crypto.Hash(v)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
44
internal/file/normalize_hashes_test.go
Normal file
44
internal/file/normalize_hashes_test.go
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
package file
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestNormalizeHashes(t *testing.T) {
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
input []crypto.Hash
|
||||||
|
want []crypto.Hash
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "deduplicate hashes",
|
||||||
|
input: []crypto.Hash{
|
||||||
|
crypto.SHA1,
|
||||||
|
crypto.SHA1,
|
||||||
|
},
|
||||||
|
want: []crypto.Hash{
|
||||||
|
crypto.SHA1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "sort hashes",
|
||||||
|
input: []crypto.Hash{
|
||||||
|
crypto.SHA512,
|
||||||
|
crypto.SHA1,
|
||||||
|
},
|
||||||
|
want: []crypto.Hash{
|
||||||
|
crypto.SHA1,
|
||||||
|
crypto.SHA512,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
assert.Equal(t, tt.want, NormalizeHashes(tt.input))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -73,6 +73,6 @@ func (cfg Config) WithSelection(selection file.Selection) Config {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (cfg Config) WithHashers(hashers []crypto.Hash) Config {
|
func (cfg Config) WithHashers(hashers []crypto.Hash) Config {
|
||||||
cfg.Hashers = hashers
|
cfg.Hashers = intFile.NormalizeHashes(hashers)
|
||||||
return cfg
|
return cfg
|
||||||
}
|
}
|
||||||
|
|||||||
@ -25,7 +25,7 @@ type Cataloger struct {
|
|||||||
|
|
||||||
func NewCataloger(hashes []crypto.Hash) *Cataloger {
|
func NewCataloger(hashes []crypto.Hash) *Cataloger {
|
||||||
return &Cataloger{
|
return &Cataloger{
|
||||||
hashes: hashes,
|
hashes: intFile.NormalizeHashes(hashes),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user