mirror of
https://github.com/aquasecurity/trivy.git
synced 2026-01-31 13:53:14 +08:00
refactor(cache): replace image and layer with artifact and blob (fanal#108)
* refactor(cache): replace image and layer with artifact and blob * fix(cache): replace S3
This commit is contained in:
@@ -88,37 +88,37 @@ func RequiredFilenames() []string {
|
||||
|
||||
type Config struct {
|
||||
Extractor extractor.Extractor
|
||||
Cache cache.ImageCache
|
||||
Cache cache.ArtifactCache
|
||||
}
|
||||
|
||||
func New(ext extractor.Extractor, c cache.ImageCache) Config {
|
||||
func New(ext extractor.Extractor, c cache.ArtifactCache) Config {
|
||||
return Config{Extractor: ext, Cache: c}
|
||||
}
|
||||
|
||||
func (ac Config) Analyze(ctx context.Context) (types.ImageReference, error) {
|
||||
func (ac Config) Analyze(ctx context.Context) (types.ArtifactReference, error) {
|
||||
imageID, err := ac.Extractor.ImageID()
|
||||
if err != nil {
|
||||
return types.ImageReference{}, xerrors.Errorf("unable to get the image ID: %w", err)
|
||||
return types.ArtifactReference{}, xerrors.Errorf("unable to get the image ID: %w", err)
|
||||
}
|
||||
|
||||
diffIDs, err := ac.Extractor.LayerIDs()
|
||||
if err != nil {
|
||||
return types.ImageReference{}, xerrors.Errorf("unable to get layer IDs: %w", err)
|
||||
return types.ArtifactReference{}, xerrors.Errorf("unable to get layer IDs: %w", err)
|
||||
}
|
||||
|
||||
missingImage, missingLayers, err := ac.Cache.MissingLayers(imageID, diffIDs)
|
||||
missingImage, missingLayers, err := ac.Cache.MissingBlobs(imageID, diffIDs)
|
||||
if err != nil {
|
||||
return types.ImageReference{}, xerrors.Errorf("unable to get missing layers: %w", err)
|
||||
return types.ArtifactReference{}, xerrors.Errorf("unable to get missing layers: %w", err)
|
||||
}
|
||||
|
||||
if err := ac.analyze(ctx, imageID, missingImage, missingLayers); err != nil {
|
||||
return types.ImageReference{}, xerrors.Errorf("analyze error: %w", err)
|
||||
return types.ArtifactReference{}, xerrors.Errorf("analyze error: %w", err)
|
||||
}
|
||||
|
||||
return types.ImageReference{
|
||||
Name: ac.Extractor.ImageName(),
|
||||
ID: imageID,
|
||||
LayerIDs: diffIDs,
|
||||
return types.ArtifactReference{
|
||||
Name: ac.Extractor.ImageName(),
|
||||
ID: imageID,
|
||||
BlobIDs: diffIDs,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -134,7 +134,7 @@ func (ac Config) analyze(ctx context.Context, imageID string, missingImage bool,
|
||||
errCh <- xerrors.Errorf("failed to analyze layer: %s : %w", diffID, err)
|
||||
return
|
||||
}
|
||||
if err = ac.Cache.PutLayer(diffID, layerInfo); err != nil {
|
||||
if err = ac.Cache.PutBlob(diffID, layerInfo); err != nil {
|
||||
errCh <- xerrors.Errorf("failed to store layer: %s in cache: %w", diffID, err)
|
||||
return
|
||||
}
|
||||
@@ -164,26 +164,26 @@ func (ac Config) analyze(ctx context.Context, imageID string, missingImage bool,
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ac Config) analyzeLayer(diffID string) (types.LayerInfo, error) {
|
||||
func (ac Config) analyzeLayer(diffID string) (types.BlobInfo, error) {
|
||||
layerDigest, files, opqDirs, whFiles, err := ac.Extractor.ExtractLayerFiles(diffID, RequiredFilenames())
|
||||
if err != nil {
|
||||
return types.LayerInfo{}, xerrors.Errorf("unable to extract files from layer %s: %w", diffID, err)
|
||||
return types.BlobInfo{}, xerrors.Errorf("unable to extract files from layer %s: %w", diffID, err)
|
||||
}
|
||||
|
||||
os := GetOS(files)
|
||||
pkgs, err := GetPackages(files)
|
||||
if err != nil {
|
||||
return types.LayerInfo{}, xerrors.Errorf("failed to get packages: %w", err)
|
||||
return types.BlobInfo{}, xerrors.Errorf("failed to get packages: %w", err)
|
||||
}
|
||||
apps, err := GetLibraries(files)
|
||||
if err != nil {
|
||||
return types.LayerInfo{}, xerrors.Errorf("failed to get libraries: %w", err)
|
||||
return types.BlobInfo{}, xerrors.Errorf("failed to get libraries: %w", err)
|
||||
}
|
||||
|
||||
layerInfo := types.LayerInfo{
|
||||
layerInfo := types.BlobInfo{
|
||||
Digest: layerDigest,
|
||||
DiffID: diffID,
|
||||
SchemaVersion: types.LayerJSONSchemaVersion,
|
||||
SchemaVersion: types.BlobJSONSchemaVersion,
|
||||
OS: os,
|
||||
PackageInfos: pkgs,
|
||||
Applications: apps,
|
||||
@@ -210,8 +210,8 @@ func (ac Config) analyzeConfig(imageID string, osFound types.OS) error {
|
||||
return xerrors.Errorf("json marshal error: %w", err)
|
||||
}
|
||||
|
||||
info := types.ImageInfo{
|
||||
SchemaVersion: types.ImageJSONSchemaVersion,
|
||||
info := types.ArtifactInfo{
|
||||
SchemaVersion: types.ArtifactJSONSchemaVersion,
|
||||
Architecture: s1.Architecture,
|
||||
Created: s1.Created.Time,
|
||||
DockerVersion: s1.DockerVersion,
|
||||
@@ -219,7 +219,7 @@ func (ac Config) analyzeConfig(imageID string, osFound types.OS) error {
|
||||
HistoryPackages: pkgs,
|
||||
}
|
||||
|
||||
if err := ac.Cache.PutImage(imageID, info); err != nil {
|
||||
if err := ac.Cache.PutArtifact(imageID, info); err != nil {
|
||||
return xerrors.Errorf("failed to put image info into the cache: %w", err)
|
||||
}
|
||||
|
||||
@@ -227,19 +227,19 @@ func (ac Config) analyzeConfig(imageID string, osFound types.OS) error {
|
||||
}
|
||||
|
||||
type Applier struct {
|
||||
cache cache.LocalImageCache
|
||||
cache cache.LocalArtifactCache
|
||||
}
|
||||
|
||||
func NewApplier(c cache.LocalImageCache) Applier {
|
||||
func NewApplier(c cache.LocalArtifactCache) Applier {
|
||||
return Applier{cache: c}
|
||||
}
|
||||
|
||||
func (a Applier) ApplyLayers(imageID string, diffIDs []string) (types.ImageDetail, error) {
|
||||
var layers []types.LayerInfo
|
||||
func (a Applier) ApplyLayers(imageID string, diffIDs []string) (types.ArtifactDetail, error) {
|
||||
var layers []types.BlobInfo
|
||||
for _, diffID := range diffIDs {
|
||||
layer, _ := a.cache.GetLayer(diffID)
|
||||
layer, _ := a.cache.GetBlob(diffID)
|
||||
if layer.SchemaVersion == 0 {
|
||||
return types.ImageDetail{}, xerrors.Errorf("layer cache missing: %s", diffID)
|
||||
return types.ArtifactDetail{}, xerrors.Errorf("layer cache missing: %s", diffID)
|
||||
}
|
||||
layers = append(layers, layer)
|
||||
}
|
||||
@@ -251,7 +251,7 @@ func (a Applier) ApplyLayers(imageID string, diffIDs []string) (types.ImageDetai
|
||||
return mergedLayer, ErrNoPkgsDetected // send back package and apps info regardless
|
||||
}
|
||||
|
||||
imageInfo, _ := a.cache.GetImage(imageID)
|
||||
imageInfo, _ := a.cache.GetArtifact(imageID)
|
||||
mergedLayer.HistoryPackages = imageInfo.HistoryPackages
|
||||
|
||||
return mergedLayer, nil
|
||||
|
||||
@@ -29,7 +29,7 @@ import (
|
||||
func TestConfig_Analyze(t *testing.T) {
|
||||
type fields struct {
|
||||
Extractor extractor.Extractor
|
||||
Cache cache.ImageCache
|
||||
Cache cache.ArtifactCache
|
||||
}
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
@@ -39,30 +39,30 @@ func TestConfig_Analyze(t *testing.T) {
|
||||
imagePath string
|
||||
fields fields
|
||||
args args
|
||||
missingLayerExpectation cache.ImageCacheMissingLayersExpectation
|
||||
putLayerExpectations []cache.ImageCachePutLayerExpectation
|
||||
putImageExpectations []cache.ImageCachePutImageExpectation
|
||||
want types.ImageReference
|
||||
missingLayerExpectation cache.ArtifactCacheMissingBlobsExpectation
|
||||
putLayerExpectations []cache.ArtifactCachePutBlobExpectation
|
||||
putImageExpectations []cache.ArtifactCachePutArtifactExpectation
|
||||
want types.ArtifactReference
|
||||
wantErr string
|
||||
}{
|
||||
{
|
||||
name: "happy path",
|
||||
imagePath: "testdata/alpine.tar.gz",
|
||||
missingLayerExpectation: cache.ImageCacheMissingLayersExpectation{
|
||||
Args: cache.ImageCacheMissingLayersArgs{
|
||||
ImageID: "sha256:965ea09ff2ebd2b9eeec88cd822ce156f6674c7e99be082c7efac3c62f3ff652",
|
||||
LayerIDs: []string{"sha256:77cae8ab23bf486355d1b3191259705374f4a11d483b24964d2f729dd8c076a0"},
|
||||
missingLayerExpectation: cache.ArtifactCacheMissingBlobsExpectation{
|
||||
Args: cache.ArtifactCacheMissingBlobsArgs{
|
||||
ArtifactID: "sha256:965ea09ff2ebd2b9eeec88cd822ce156f6674c7e99be082c7efac3c62f3ff652",
|
||||
BlobIDs: []string{"sha256:77cae8ab23bf486355d1b3191259705374f4a11d483b24964d2f729dd8c076a0"},
|
||||
},
|
||||
Returns: cache.ImageCacheMissingLayersReturns{
|
||||
MissingImage: true,
|
||||
MissingLayerIDs: []string{"sha256:77cae8ab23bf486355d1b3191259705374f4a11d483b24964d2f729dd8c076a0"},
|
||||
Returns: cache.ArtifactCacheMissingBlobsReturns{
|
||||
MissingArtifact: true,
|
||||
MissingBlobIDs: []string{"sha256:77cae8ab23bf486355d1b3191259705374f4a11d483b24964d2f729dd8c076a0"},
|
||||
},
|
||||
},
|
||||
putLayerExpectations: []cache.ImageCachePutLayerExpectation{
|
||||
putLayerExpectations: []cache.ArtifactCachePutBlobExpectation{
|
||||
{
|
||||
Args: cache.ImageCachePutLayerArgs{
|
||||
DiffID: "sha256:77cae8ab23bf486355d1b3191259705374f4a11d483b24964d2f729dd8c076a0",
|
||||
LayerInfo: types.LayerInfo{
|
||||
Args: cache.ArtifactCachePutBlobArgs{
|
||||
BlobID: "sha256:77cae8ab23bf486355d1b3191259705374f4a11d483b24964d2f729dd8c076a0",
|
||||
BlobInfo: types.BlobInfo{
|
||||
SchemaVersion: 1,
|
||||
Digest: "",
|
||||
DiffID: "sha256:77cae8ab23bf486355d1b3191259705374f4a11d483b24964d2f729dd8c076a0",
|
||||
@@ -76,14 +76,14 @@ func TestConfig_Analyze(t *testing.T) {
|
||||
WhiteoutFiles: []string(nil),
|
||||
},
|
||||
},
|
||||
Returns: cache.ImageCachePutLayerReturns{},
|
||||
Returns: cache.ArtifactCachePutBlobReturns{},
|
||||
},
|
||||
},
|
||||
putImageExpectations: []cache.ImageCachePutImageExpectation{
|
||||
putImageExpectations: []cache.ArtifactCachePutArtifactExpectation{
|
||||
{
|
||||
Args: cache.ImageCachePutImageArgs{
|
||||
ImageID: "sha256:965ea09ff2ebd2b9eeec88cd822ce156f6674c7e99be082c7efac3c62f3ff652",
|
||||
ImageInfo: types.ImageInfo{
|
||||
Args: cache.ArtifactCachePutArtifactArgs{
|
||||
ArtifactID: "sha256:965ea09ff2ebd2b9eeec88cd822ce156f6674c7e99be082c7efac3c62f3ff652",
|
||||
ArtifactInfo: types.ArtifactInfo{
|
||||
SchemaVersion: 1,
|
||||
Architecture: "amd64",
|
||||
Created: time.Date(2019, 10, 21, 17, 21, 42, 387111039, time.UTC),
|
||||
@@ -93,38 +93,38 @@ func TestConfig_Analyze(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
want: types.ImageReference{
|
||||
Name: "testdata/alpine.tar.gz",
|
||||
ID: "sha256:965ea09ff2ebd2b9eeec88cd822ce156f6674c7e99be082c7efac3c62f3ff652",
|
||||
LayerIDs: []string{"sha256:77cae8ab23bf486355d1b3191259705374f4a11d483b24964d2f729dd8c076a0"},
|
||||
want: types.ArtifactReference{
|
||||
Name: "testdata/alpine.tar.gz",
|
||||
ID: "sha256:965ea09ff2ebd2b9eeec88cd822ce156f6674c7e99be082c7efac3c62f3ff652",
|
||||
BlobIDs: []string{"sha256:77cae8ab23bf486355d1b3191259705374f4a11d483b24964d2f729dd8c076a0"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "happy path: include lock files",
|
||||
imagePath: "testdata/vuln-image.tar.gz",
|
||||
missingLayerExpectation: cache.ImageCacheMissingLayersExpectation{
|
||||
Args: cache.ImageCacheMissingLayersArgs{
|
||||
ImageID: "sha256:58701fd185bda36cab0557bb6438661831267aa4a9e0b54211c4d5317a48aff4",
|
||||
LayerIDs: []string{
|
||||
missingLayerExpectation: cache.ArtifactCacheMissingBlobsExpectation{
|
||||
Args: cache.ArtifactCacheMissingBlobsArgs{
|
||||
ArtifactID: "sha256:58701fd185bda36cab0557bb6438661831267aa4a9e0b54211c4d5317a48aff4",
|
||||
BlobIDs: []string{
|
||||
"sha256:932da51564135c98a49a34a193d6cd363d8fa4184d957fde16c9d8527b3f3b02",
|
||||
"sha256:dffd9992ca398466a663c87c92cfea2a2db0ae0cf33fcb99da60eec52addbfc5",
|
||||
"sha256:24df0d4e20c0f42d3703bf1f1db2bdd77346c7956f74f423603d651e8e5ae8a7",
|
||||
"sha256:a4595c43a874856bf95f3bfc4fbf78bbaa04c92c726276d4f64193a47ced0566",
|
||||
},
|
||||
},
|
||||
Returns: cache.ImageCacheMissingLayersReturns{
|
||||
MissingLayerIDs: []string{
|
||||
Returns: cache.ArtifactCacheMissingBlobsReturns{
|
||||
MissingBlobIDs: []string{
|
||||
"sha256:932da51564135c98a49a34a193d6cd363d8fa4184d957fde16c9d8527b3f3b02",
|
||||
"sha256:dffd9992ca398466a663c87c92cfea2a2db0ae0cf33fcb99da60eec52addbfc5",
|
||||
"sha256:24df0d4e20c0f42d3703bf1f1db2bdd77346c7956f74f423603d651e8e5ae8a7",
|
||||
},
|
||||
},
|
||||
},
|
||||
putLayerExpectations: []cache.ImageCachePutLayerExpectation{
|
||||
putLayerExpectations: []cache.ArtifactCachePutBlobExpectation{
|
||||
{
|
||||
Args: cache.ImageCachePutLayerArgs{
|
||||
DiffID: "sha256:932da51564135c98a49a34a193d6cd363d8fa4184d957fde16c9d8527b3f3b02",
|
||||
LayerInfo: types.LayerInfo{
|
||||
Args: cache.ArtifactCachePutBlobArgs{
|
||||
BlobID: "sha256:932da51564135c98a49a34a193d6cd363d8fa4184d957fde16c9d8527b3f3b02",
|
||||
BlobInfo: types.BlobInfo{
|
||||
SchemaVersion: 1,
|
||||
Digest: "",
|
||||
DiffID: "sha256:932da51564135c98a49a34a193d6cd363d8fa4184d957fde16c9d8527b3f3b02",
|
||||
@@ -134,9 +134,9 @@ func TestConfig_Analyze(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
Args: cache.ImageCachePutLayerArgs{
|
||||
DiffID: "sha256:dffd9992ca398466a663c87c92cfea2a2db0ae0cf33fcb99da60eec52addbfc5",
|
||||
LayerInfo: types.LayerInfo{
|
||||
Args: cache.ArtifactCachePutBlobArgs{
|
||||
BlobID: "sha256:dffd9992ca398466a663c87c92cfea2a2db0ae0cf33fcb99da60eec52addbfc5",
|
||||
BlobInfo: types.BlobInfo{
|
||||
SchemaVersion: 1,
|
||||
Digest: "",
|
||||
DiffID: "sha256:dffd9992ca398466a663c87c92cfea2a2db0ae0cf33fcb99da60eec52addbfc5",
|
||||
@@ -145,9 +145,9 @@ func TestConfig_Analyze(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
Args: cache.ImageCachePutLayerArgs{
|
||||
DiffID: "sha256:24df0d4e20c0f42d3703bf1f1db2bdd77346c7956f74f423603d651e8e5ae8a7",
|
||||
LayerInfo: types.LayerInfo{
|
||||
Args: cache.ArtifactCachePutBlobArgs{
|
||||
BlobID: "sha256:24df0d4e20c0f42d3703bf1f1db2bdd77346c7956f74f423603d651e8e5ae8a7",
|
||||
BlobInfo: types.BlobInfo{
|
||||
SchemaVersion: 1,
|
||||
Digest: "",
|
||||
DiffID: "sha256:24df0d4e20c0f42d3703bf1f1db2bdd77346c7956f74f423603d651e8e5ae8a7",
|
||||
@@ -174,10 +174,10 @@ func TestConfig_Analyze(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
want: types.ImageReference{
|
||||
want: types.ArtifactReference{
|
||||
Name: "testdata/vuln-image.tar.gz",
|
||||
ID: "sha256:58701fd185bda36cab0557bb6438661831267aa4a9e0b54211c4d5317a48aff4",
|
||||
LayerIDs: []string{
|
||||
BlobIDs: []string{
|
||||
"sha256:932da51564135c98a49a34a193d6cd363d8fa4184d957fde16c9d8527b3f3b02",
|
||||
"sha256:dffd9992ca398466a663c87c92cfea2a2db0ae0cf33fcb99da60eec52addbfc5",
|
||||
"sha256:24df0d4e20c0f42d3703bf1f1db2bdd77346c7956f74f423603d651e8e5ae8a7",
|
||||
@@ -186,36 +186,36 @@ func TestConfig_Analyze(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "sad path, MissingLayers returns an error",
|
||||
name: "sad path, MissingBlobs returns an error",
|
||||
imagePath: "testdata/alpine.tar.gz",
|
||||
missingLayerExpectation: cache.ImageCacheMissingLayersExpectation{
|
||||
Args: cache.ImageCacheMissingLayersArgs{
|
||||
ImageID: "sha256:965ea09ff2ebd2b9eeec88cd822ce156f6674c7e99be082c7efac3c62f3ff652",
|
||||
LayerIDs: []string{"sha256:77cae8ab23bf486355d1b3191259705374f4a11d483b24964d2f729dd8c076a0"},
|
||||
missingLayerExpectation: cache.ArtifactCacheMissingBlobsExpectation{
|
||||
Args: cache.ArtifactCacheMissingBlobsArgs{
|
||||
ArtifactID: "sha256:965ea09ff2ebd2b9eeec88cd822ce156f6674c7e99be082c7efac3c62f3ff652",
|
||||
BlobIDs: []string{"sha256:77cae8ab23bf486355d1b3191259705374f4a11d483b24964d2f729dd8c076a0"},
|
||||
},
|
||||
Returns: cache.ImageCacheMissingLayersReturns{
|
||||
Err: xerrors.New("MissingLayers failed"),
|
||||
Returns: cache.ArtifactCacheMissingBlobsReturns{
|
||||
Err: xerrors.New("MissingBlobs failed"),
|
||||
},
|
||||
},
|
||||
wantErr: "MissingLayers failed",
|
||||
wantErr: "MissingBlobs failed",
|
||||
},
|
||||
{
|
||||
name: "sad path, PutLayer returns an error",
|
||||
name: "sad path, PutBlob returns an error",
|
||||
imagePath: "testdata/alpine.tar.gz",
|
||||
missingLayerExpectation: cache.ImageCacheMissingLayersExpectation{
|
||||
Args: cache.ImageCacheMissingLayersArgs{
|
||||
ImageID: "sha256:965ea09ff2ebd2b9eeec88cd822ce156f6674c7e99be082c7efac3c62f3ff652",
|
||||
LayerIDs: []string{"sha256:77cae8ab23bf486355d1b3191259705374f4a11d483b24964d2f729dd8c076a0"},
|
||||
missingLayerExpectation: cache.ArtifactCacheMissingBlobsExpectation{
|
||||
Args: cache.ArtifactCacheMissingBlobsArgs{
|
||||
ArtifactID: "sha256:965ea09ff2ebd2b9eeec88cd822ce156f6674c7e99be082c7efac3c62f3ff652",
|
||||
BlobIDs: []string{"sha256:77cae8ab23bf486355d1b3191259705374f4a11d483b24964d2f729dd8c076a0"},
|
||||
},
|
||||
Returns: cache.ImageCacheMissingLayersReturns{
|
||||
MissingLayerIDs: []string{"sha256:77cae8ab23bf486355d1b3191259705374f4a11d483b24964d2f729dd8c076a0"},
|
||||
Returns: cache.ArtifactCacheMissingBlobsReturns{
|
||||
MissingBlobIDs: []string{"sha256:77cae8ab23bf486355d1b3191259705374f4a11d483b24964d2f729dd8c076a0"},
|
||||
},
|
||||
},
|
||||
putLayerExpectations: []cache.ImageCachePutLayerExpectation{
|
||||
putLayerExpectations: []cache.ArtifactCachePutBlobExpectation{
|
||||
{
|
||||
Args: cache.ImageCachePutLayerArgs{
|
||||
DiffID: "sha256:77cae8ab23bf486355d1b3191259705374f4a11d483b24964d2f729dd8c076a0",
|
||||
LayerInfo: types.LayerInfo{
|
||||
Args: cache.ArtifactCachePutBlobArgs{
|
||||
BlobID: "sha256:77cae8ab23bf486355d1b3191259705374f4a11d483b24964d2f729dd8c076a0",
|
||||
BlobInfo: types.BlobInfo{
|
||||
SchemaVersion: 1,
|
||||
Digest: "",
|
||||
DiffID: "sha256:77cae8ab23bf486355d1b3191259705374f4a11d483b24964d2f729dd8c076a0",
|
||||
@@ -229,7 +229,7 @@ func TestConfig_Analyze(t *testing.T) {
|
||||
WhiteoutFiles: []string(nil),
|
||||
},
|
||||
},
|
||||
Returns: cache.ImageCachePutLayerReturns{
|
||||
Returns: cache.ArtifactCachePutBlobReturns{
|
||||
Err: errors.New("put layer failed"),
|
||||
},
|
||||
},
|
||||
@@ -239,10 +239,10 @@ func TestConfig_Analyze(t *testing.T) {
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
mockCache := new(cache.MockImageCache)
|
||||
mockCache.ApplyMissingLayersExpectation(tt.missingLayerExpectation)
|
||||
mockCache.ApplyPutLayerExpectations(tt.putLayerExpectations)
|
||||
mockCache.ApplyPutImageExpectations(tt.putImageExpectations)
|
||||
mockCache := new(cache.MockArtifactCache)
|
||||
mockCache.ApplyMissingBlobsExpectation(tt.missingLayerExpectation)
|
||||
mockCache.ApplyPutBlobExpectations(tt.putLayerExpectations)
|
||||
mockCache.ApplyPutArtifactExpectations(tt.putImageExpectations)
|
||||
|
||||
d, err := docker.NewArchiveImageExtractor(tt.imagePath)
|
||||
require.NoError(t, err, tt.name)
|
||||
@@ -268,9 +268,9 @@ func TestApplier_ApplyLayers(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
getLayerExpectations []cache.LocalImageCacheGetLayerExpectation
|
||||
getImageExpectations []cache.LocalImageCacheGetImageExpectation
|
||||
want types.ImageDetail
|
||||
getLayerExpectations []cache.LocalArtifactCacheGetBlobExpectation
|
||||
getImageExpectations []cache.LocalArtifactCacheGetArtifactExpectation
|
||||
want types.ArtifactDetail
|
||||
wantErr string
|
||||
}{
|
||||
{
|
||||
@@ -283,13 +283,13 @@ func TestApplier_ApplyLayers(t *testing.T) {
|
||||
"sha256:24df0d4e20c0f42d3703bf1f1db2bdd77346c7956f74f423603d651e8e5ae8a7",
|
||||
},
|
||||
},
|
||||
getLayerExpectations: []cache.LocalImageCacheGetLayerExpectation{
|
||||
getLayerExpectations: []cache.LocalArtifactCacheGetBlobExpectation{
|
||||
{
|
||||
Args: cache.LocalImageCacheGetLayerArgs{
|
||||
DiffID: "sha256:932da51564135c98a49a34a193d6cd363d8fa4184d957fde16c9d8527b3f3b02",
|
||||
Args: cache.LocalArtifactCacheGetBlobArgs{
|
||||
BlobID: "sha256:932da51564135c98a49a34a193d6cd363d8fa4184d957fde16c9d8527b3f3b02",
|
||||
},
|
||||
Returns: cache.LocalImageCacheGetLayerReturns{
|
||||
LayerInfo: types.LayerInfo{
|
||||
Returns: cache.LocalArtifactCacheGetBlobReturns{
|
||||
BlobInfo: types.BlobInfo{
|
||||
SchemaVersion: 1,
|
||||
Digest: "sha256:932da51564135c98a49a34a193d6cd363d8fa4184d957fde16c9d8527b3f3b02",
|
||||
DiffID: "sha256:a187dde48cd289ac374ad8539930628314bc581a481cdb41409c9289419ddb72",
|
||||
@@ -314,11 +314,11 @@ func TestApplier_ApplyLayers(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
Args: cache.LocalImageCacheGetLayerArgs{
|
||||
DiffID: "sha256:dffd9992ca398466a663c87c92cfea2a2db0ae0cf33fcb99da60eec52addbfc5",
|
||||
Args: cache.LocalArtifactCacheGetBlobArgs{
|
||||
BlobID: "sha256:dffd9992ca398466a663c87c92cfea2a2db0ae0cf33fcb99da60eec52addbfc5",
|
||||
},
|
||||
Returns: cache.LocalImageCacheGetLayerReturns{
|
||||
LayerInfo: types.LayerInfo{
|
||||
Returns: cache.LocalArtifactCacheGetBlobReturns{
|
||||
BlobInfo: types.BlobInfo{
|
||||
SchemaVersion: 1,
|
||||
Digest: "sha256:dffd9992ca398466a663c87c92cfea2a2db0ae0cf33fcb99da60eec52addbfc5",
|
||||
DiffID: "sha256:aad63a9339440e7c3e1fff2b988991b9bfb81280042fa7f39a5e327023056819",
|
||||
@@ -342,11 +342,11 @@ func TestApplier_ApplyLayers(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
Args: cache.LocalImageCacheGetLayerArgs{
|
||||
DiffID: "sha256:24df0d4e20c0f42d3703bf1f1db2bdd77346c7956f74f423603d651e8e5ae8a7",
|
||||
Args: cache.LocalArtifactCacheGetBlobArgs{
|
||||
BlobID: "sha256:24df0d4e20c0f42d3703bf1f1db2bdd77346c7956f74f423603d651e8e5ae8a7",
|
||||
},
|
||||
Returns: cache.LocalImageCacheGetLayerReturns{
|
||||
LayerInfo: types.LayerInfo{
|
||||
Returns: cache.LocalArtifactCacheGetBlobReturns{
|
||||
BlobInfo: types.BlobInfo{
|
||||
SchemaVersion: 1,
|
||||
Digest: "sha256:beee9f30bc1f711043e78d4a2be0668955d4b761d587d6f60c2c8dc081efb203",
|
||||
DiffID: "sha256:24df0d4e20c0f42d3703bf1f1db2bdd77346c7956f74f423603d651e8e5ae8a7",
|
||||
@@ -374,19 +374,19 @@ func TestApplier_ApplyLayers(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
getImageExpectations: []cache.LocalImageCacheGetImageExpectation{
|
||||
getImageExpectations: []cache.LocalArtifactCacheGetArtifactExpectation{
|
||||
{
|
||||
Args: cache.LocalImageCacheGetImageArgs{
|
||||
ImageID: "sha256:4791503518dff090d6a82f7a5c1fd71c41146920e2562fb64308e17ab6834b7e",
|
||||
Args: cache.LocalArtifactCacheGetArtifactArgs{
|
||||
ArtifactID: "sha256:4791503518dff090d6a82f7a5c1fd71c41146920e2562fb64308e17ab6834b7e",
|
||||
},
|
||||
Returns: cache.LocalImageCacheGetImageReturns{
|
||||
ImageInfo: types.ImageInfo{
|
||||
Returns: cache.LocalArtifactCacheGetArtifactReturns{
|
||||
ArtifactInfo: types.ArtifactInfo{
|
||||
SchemaVersion: 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
want: types.ImageDetail{
|
||||
want: types.ArtifactDetail{
|
||||
OS: &types.OS{
|
||||
Family: "debian",
|
||||
Name: "9.9",
|
||||
@@ -444,13 +444,13 @@ func TestApplier_ApplyLayers(t *testing.T) {
|
||||
"sha256:531743b7098cb2aaf615641007a129173f63ed86ca32fe7b5a246a1c47286028",
|
||||
},
|
||||
},
|
||||
getLayerExpectations: []cache.LocalImageCacheGetLayerExpectation{
|
||||
getLayerExpectations: []cache.LocalArtifactCacheGetBlobExpectation{
|
||||
{
|
||||
Args: cache.LocalImageCacheGetLayerArgs{
|
||||
DiffID: "sha256:531743b7098cb2aaf615641007a129173f63ed86ca32fe7b5a246a1c47286028",
|
||||
Args: cache.LocalArtifactCacheGetBlobArgs{
|
||||
BlobID: "sha256:531743b7098cb2aaf615641007a129173f63ed86ca32fe7b5a246a1c47286028",
|
||||
},
|
||||
Returns: cache.LocalImageCacheGetLayerReturns{
|
||||
LayerInfo: types.LayerInfo{
|
||||
Returns: cache.LocalArtifactCacheGetBlobReturns{
|
||||
BlobInfo: types.BlobInfo{
|
||||
SchemaVersion: 1,
|
||||
Digest: "sha256:a187dde48cd289ac374ad8539930628314bc581a481cdb41409c9289419ddb72",
|
||||
DiffID: "sha256:531743b7098cb2aaf615641007a129173f63ed86ca32fe7b5a246a1c47286028",
|
||||
@@ -474,13 +474,13 @@ func TestApplier_ApplyLayers(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
getImageExpectations: []cache.LocalImageCacheGetImageExpectation{
|
||||
getImageExpectations: []cache.LocalArtifactCacheGetArtifactExpectation{
|
||||
{
|
||||
Args: cache.LocalImageCacheGetImageArgs{
|
||||
ImageID: "sha256:3bb70bd5fb37e05b8ecaaace5d6a6b5ec7834037c07ecb5907355c23ab70352d",
|
||||
Args: cache.LocalArtifactCacheGetArtifactArgs{
|
||||
ArtifactID: "sha256:3bb70bd5fb37e05b8ecaaace5d6a6b5ec7834037c07ecb5907355c23ab70352d",
|
||||
},
|
||||
Returns: cache.LocalImageCacheGetImageReturns{
|
||||
ImageInfo: types.ImageInfo{
|
||||
Returns: cache.LocalArtifactCacheGetArtifactReturns{
|
||||
ArtifactInfo: types.ArtifactInfo{
|
||||
SchemaVersion: 1,
|
||||
HistoryPackages: []types.Package{
|
||||
{Name: "musl", Version: "1.1.23"},
|
||||
@@ -496,7 +496,7 @@ func TestApplier_ApplyLayers(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
want: types.ImageDetail{
|
||||
want: types.ArtifactDetail{
|
||||
OS: &types.OS{
|
||||
Family: "alpine",
|
||||
Name: "3.10.4",
|
||||
@@ -556,35 +556,35 @@ func TestApplier_ApplyLayers(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "sad path GetLayer returns an error",
|
||||
name: "sad path GetBlob returns an error",
|
||||
args: args{
|
||||
layerIDs: []string{
|
||||
"sha256:932da51564135c98a49a34a193d6cd363d8fa4184d957fde16c9d8527b3f3b02",
|
||||
},
|
||||
},
|
||||
getLayerExpectations: []cache.LocalImageCacheGetLayerExpectation{
|
||||
getLayerExpectations: []cache.LocalArtifactCacheGetBlobExpectation{
|
||||
{
|
||||
Args: cache.LocalImageCacheGetLayerArgs{
|
||||
DiffID: "sha256:932da51564135c98a49a34a193d6cd363d8fa4184d957fde16c9d8527b3f3b02",
|
||||
Args: cache.LocalArtifactCacheGetBlobArgs{
|
||||
BlobID: "sha256:932da51564135c98a49a34a193d6cd363d8fa4184d957fde16c9d8527b3f3b02",
|
||||
},
|
||||
Returns: cache.LocalImageCacheGetLayerReturns{LayerInfo: types.LayerInfo{}},
|
||||
Returns: cache.LocalArtifactCacheGetBlobReturns{BlobInfo: types.BlobInfo{}},
|
||||
},
|
||||
},
|
||||
wantErr: "layer cache missing",
|
||||
},
|
||||
{
|
||||
name: "sad path GetLayer returns empty layer info",
|
||||
name: "sad path GetBlob returns empty layer info",
|
||||
args: args{
|
||||
layerIDs: []string{
|
||||
"sha256:932da51564135c98a49a34a193d6cd363d8fa4184d957fde16c9d8527b3f3b02",
|
||||
},
|
||||
},
|
||||
getLayerExpectations: []cache.LocalImageCacheGetLayerExpectation{
|
||||
getLayerExpectations: []cache.LocalArtifactCacheGetBlobExpectation{
|
||||
{
|
||||
Args: cache.LocalImageCacheGetLayerArgs{
|
||||
DiffID: "sha256:932da51564135c98a49a34a193d6cd363d8fa4184d957fde16c9d8527b3f3b02",
|
||||
Args: cache.LocalArtifactCacheGetBlobArgs{
|
||||
BlobID: "sha256:932da51564135c98a49a34a193d6cd363d8fa4184d957fde16c9d8527b3f3b02",
|
||||
},
|
||||
Returns: cache.LocalImageCacheGetLayerReturns{LayerInfo: types.LayerInfo{}},
|
||||
Returns: cache.LocalArtifactCacheGetBlobReturns{BlobInfo: types.BlobInfo{}},
|
||||
},
|
||||
},
|
||||
wantErr: "layer cache missing",
|
||||
@@ -599,13 +599,13 @@ func TestApplier_ApplyLayers(t *testing.T) {
|
||||
"sha256:24df0d4e20c0f42d3703bf1f1db2bdd77346c7956f74f423603d651e8e5ae8a7",
|
||||
},
|
||||
},
|
||||
getLayerExpectations: []cache.LocalImageCacheGetLayerExpectation{
|
||||
getLayerExpectations: []cache.LocalArtifactCacheGetBlobExpectation{
|
||||
{
|
||||
Args: cache.LocalImageCacheGetLayerArgs{
|
||||
DiffID: "sha256:932da51564135c98a49a34a193d6cd363d8fa4184d957fde16c9d8527b3f3b02",
|
||||
Args: cache.LocalArtifactCacheGetBlobArgs{
|
||||
BlobID: "sha256:932da51564135c98a49a34a193d6cd363d8fa4184d957fde16c9d8527b3f3b02",
|
||||
},
|
||||
Returns: cache.LocalImageCacheGetLayerReturns{
|
||||
LayerInfo: types.LayerInfo{
|
||||
Returns: cache.LocalArtifactCacheGetBlobReturns{
|
||||
BlobInfo: types.BlobInfo{
|
||||
SchemaVersion: 1,
|
||||
Digest: "sha256:932da51564135c98a49a34a193d6cd363d8fa4184d957fde16c9d8527b3f3b02",
|
||||
DiffID: "sha256:a187dde48cd289ac374ad8539930628314bc581a481cdb41409c9289419ddb72",
|
||||
@@ -626,11 +626,11 @@ func TestApplier_ApplyLayers(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
Args: cache.LocalImageCacheGetLayerArgs{
|
||||
DiffID: "sha256:dffd9992ca398466a663c87c92cfea2a2db0ae0cf33fcb99da60eec52addbfc5",
|
||||
Args: cache.LocalArtifactCacheGetBlobArgs{
|
||||
BlobID: "sha256:dffd9992ca398466a663c87c92cfea2a2db0ae0cf33fcb99da60eec52addbfc5",
|
||||
},
|
||||
Returns: cache.LocalImageCacheGetLayerReturns{
|
||||
LayerInfo: types.LayerInfo{
|
||||
Returns: cache.LocalArtifactCacheGetBlobReturns{
|
||||
BlobInfo: types.BlobInfo{
|
||||
SchemaVersion: 1,
|
||||
Digest: "sha256:dffd9992ca398466a663c87c92cfea2a2db0ae0cf33fcb99da60eec52addbfc5",
|
||||
DiffID: "sha256:aad63a9339440e7c3e1fff2b988991b9bfb81280042fa7f39a5e327023056819",
|
||||
@@ -654,11 +654,11 @@ func TestApplier_ApplyLayers(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
Args: cache.LocalImageCacheGetLayerArgs{
|
||||
DiffID: "sha256:24df0d4e20c0f42d3703bf1f1db2bdd77346c7956f74f423603d651e8e5ae8a7",
|
||||
Args: cache.LocalArtifactCacheGetBlobArgs{
|
||||
BlobID: "sha256:24df0d4e20c0f42d3703bf1f1db2bdd77346c7956f74f423603d651e8e5ae8a7",
|
||||
},
|
||||
Returns: cache.LocalImageCacheGetLayerReturns{
|
||||
LayerInfo: types.LayerInfo{
|
||||
Returns: cache.LocalArtifactCacheGetBlobReturns{
|
||||
BlobInfo: types.BlobInfo{
|
||||
SchemaVersion: 1,
|
||||
Digest: "sha256:beee9f30bc1f711043e78d4a2be0668955d4b761d587d6f60c2c8dc081efb203",
|
||||
DiffID: "sha256:24df0d4e20c0f42d3703bf1f1db2bdd77346c7956f74f423603d651e8e5ae8a7",
|
||||
@@ -686,7 +686,7 @@ func TestApplier_ApplyLayers(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
want: types.ImageDetail{
|
||||
want: types.ArtifactDetail{
|
||||
Packages: []types.Package{
|
||||
{
|
||||
Name: "libc6", Version: "2.24-11+deb9u4", SrcName: "glibc", SrcVersion: "2.24-11+deb9u4",
|
||||
@@ -740,13 +740,13 @@ func TestApplier_ApplyLayers(t *testing.T) {
|
||||
"sha256:932da51564135c98a49a34a193d6cd363d8fa4184d957fde16c9d8527b3f3b02",
|
||||
},
|
||||
},
|
||||
getLayerExpectations: []cache.LocalImageCacheGetLayerExpectation{
|
||||
getLayerExpectations: []cache.LocalArtifactCacheGetBlobExpectation{
|
||||
{
|
||||
Args: cache.LocalImageCacheGetLayerArgs{
|
||||
DiffID: "sha256:932da51564135c98a49a34a193d6cd363d8fa4184d957fde16c9d8527b3f3b02",
|
||||
Args: cache.LocalArtifactCacheGetBlobArgs{
|
||||
BlobID: "sha256:932da51564135c98a49a34a193d6cd363d8fa4184d957fde16c9d8527b3f3b02",
|
||||
},
|
||||
Returns: cache.LocalImageCacheGetLayerReturns{
|
||||
LayerInfo: types.LayerInfo{
|
||||
Returns: cache.LocalArtifactCacheGetBlobReturns{
|
||||
BlobInfo: types.BlobInfo{
|
||||
SchemaVersion: 1,
|
||||
OS: &types.OS{
|
||||
Family: "debian",
|
||||
@@ -756,7 +756,7 @@ func TestApplier_ApplyLayers(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
want: types.ImageDetail{
|
||||
want: types.ArtifactDetail{
|
||||
OS: &types.OS{
|
||||
Family: "debian",
|
||||
Name: "9.9",
|
||||
@@ -767,9 +767,9 @@ func TestApplier_ApplyLayers(t *testing.T) {
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
c := new(cache.MockLocalImageCache)
|
||||
c.ApplyGetLayerExpectations(tt.getLayerExpectations)
|
||||
c.ApplyGetImageExpectations(tt.getImageExpectations)
|
||||
c := new(cache.MockLocalArtifactCache)
|
||||
c.ApplyGetBlobExpectations(tt.getLayerExpectations)
|
||||
c.ApplyGetArtifactExpectations(tt.getImageExpectations)
|
||||
|
||||
a := analyzer.NewApplier(c)
|
||||
|
||||
|
||||
147
cache/cache.go
vendored
147
cache/cache.go
vendored
@@ -13,29 +13,41 @@ import (
|
||||
const (
|
||||
cacheDirName = "fanal"
|
||||
|
||||
// imageBucket stores image information with image ID
|
||||
imageBucket = "image"
|
||||
// layerBucket stores os, package and library information per layer ID
|
||||
layerBucket = "layer"
|
||||
// artifactBucket stores artifact information with artifact ID such as image ID
|
||||
artifactBucket = "artifact"
|
||||
// blobBucket stores os, package and library information per blob ID such as layer ID
|
||||
blobBucket = "blob"
|
||||
)
|
||||
|
||||
type Cache interface {
|
||||
ImageCache
|
||||
LocalImageCache
|
||||
ArtifactCache
|
||||
LocalArtifactCache
|
||||
}
|
||||
|
||||
// ImageCache uses local or remote cache
|
||||
type ImageCache interface {
|
||||
MissingLayers(imageID string, layerIDs []string) (missingImage bool, missingLayerIDs []string, err error)
|
||||
PutImage(imageID string, imageInfo types.ImageInfo) (err error)
|
||||
PutLayer(diffID string, layerInfo types.LayerInfo) (err error)
|
||||
// ArtifactCache uses local or remote cache
|
||||
type ArtifactCache interface {
|
||||
// MissingBlobs returns missing blob IDs such as layer IDs in cache
|
||||
MissingBlobs(artifactID string, blobIDs []string) (missingArtifact bool, missingBlobIDs []string, err error)
|
||||
|
||||
// PutArtifact stores artifact information such as image metadata in cache
|
||||
PutArtifact(artifactID string, artifactInfo types.ArtifactInfo) (err error)
|
||||
|
||||
// PutBlob stores blob information such as layer information in local cache
|
||||
PutBlob(blobID string, blobInfo types.BlobInfo) (err error)
|
||||
}
|
||||
|
||||
// LocalImageCache always uses local cache
|
||||
type LocalImageCache interface {
|
||||
GetImage(imageID string) (imageInfo types.ImageInfo, err error)
|
||||
GetLayer(diffID string) (layerInfo types.LayerInfo, err error)
|
||||
// LocalArtifactCache always uses local cache
|
||||
type LocalArtifactCache interface {
|
||||
// GetArtifact gets artifact information such as image metadata from local cache
|
||||
GetArtifact(artifactID string) (artifactInfo types.ArtifactInfo, err error)
|
||||
|
||||
// GetBlob gets blob information such as layer data from local cache
|
||||
GetBlob(blobID string) (blobInfo types.BlobInfo, err error)
|
||||
|
||||
// Close closes the local database
|
||||
Close() (err error)
|
||||
|
||||
// Clear deletes the local database
|
||||
Clear() (err error)
|
||||
}
|
||||
|
||||
@@ -56,7 +68,7 @@ func NewFSCache(cacheDir string) (FSCache, error) {
|
||||
}
|
||||
|
||||
err = db.Update(func(tx *bolt.Tx) error {
|
||||
for _, bucket := range []string{imageBucket, layerBucket} {
|
||||
for _, bucket := range []string{artifactBucket, blobBucket} {
|
||||
if _, err := tx.CreateBucketIfNotExists([]byte(bucket)); err != nil {
|
||||
return xerrors.Errorf("unable to create %s bucket: %w", err)
|
||||
}
|
||||
@@ -73,47 +85,49 @@ func NewFSCache(cacheDir string) (FSCache, error) {
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (fs FSCache) GetLayer(diffID string) (types.LayerInfo, error) {
|
||||
var layerInfo types.LayerInfo
|
||||
// GetBlob gets blob information such as layer data from local cache
|
||||
func (fs FSCache) GetBlob(blobID string) (types.BlobInfo, error) {
|
||||
var blobInfo types.BlobInfo
|
||||
err := fs.db.View(func(tx *bolt.Tx) error {
|
||||
var err error
|
||||
layerBucket := tx.Bucket([]byte(layerBucket))
|
||||
layerInfo, err = fs.getLayer(layerBucket, diffID)
|
||||
blobBucket := tx.Bucket([]byte(blobBucket))
|
||||
blobInfo, err = fs.getBlob(blobBucket, blobID)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("failed to get layer from the cache: %w", err)
|
||||
return xerrors.Errorf("failed to get blob from the cache: %w", err)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return types.LayerInfo{}, xerrors.Errorf("DB error: %w", err)
|
||||
return types.BlobInfo{}, xerrors.Errorf("DB error: %w", err)
|
||||
}
|
||||
return layerInfo, nil
|
||||
return blobInfo, nil
|
||||
}
|
||||
|
||||
func (fs FSCache) getLayer(layerBucket *bolt.Bucket, diffID string) (types.LayerInfo, error) {
|
||||
b := layerBucket.Get([]byte(diffID))
|
||||
func (fs FSCache) getBlob(blobBucket *bolt.Bucket, diffID string) (types.BlobInfo, error) {
|
||||
b := blobBucket.Get([]byte(diffID))
|
||||
|
||||
var l types.LayerInfo
|
||||
var l types.BlobInfo
|
||||
if err := json.Unmarshal(b, &l); err != nil {
|
||||
return types.LayerInfo{}, xerrors.Errorf("JSON unmarshal error: %w", err)
|
||||
return types.BlobInfo{}, xerrors.Errorf("JSON unmarshal error: %w", err)
|
||||
}
|
||||
return l, nil
|
||||
}
|
||||
|
||||
func (fs FSCache) PutLayer(diffID string, layerInfo types.LayerInfo) error {
|
||||
if _, err := v1.NewHash(diffID); err != nil {
|
||||
return xerrors.Errorf("invalid diffID (%s): %w", diffID, err)
|
||||
// PutBlob stores blob information such as layer information in local cache
|
||||
func (fs FSCache) PutBlob(blobID string, blobInfo types.BlobInfo) error {
|
||||
if _, err := v1.NewHash(blobID); err != nil {
|
||||
return xerrors.Errorf("invalid diffID (%s): %w", blobID, err)
|
||||
}
|
||||
|
||||
b, err := json.Marshal(layerInfo)
|
||||
b, err := json.Marshal(blobInfo)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("unable to marshal layer JSON (%s): %w", diffID, err)
|
||||
return xerrors.Errorf("unable to marshal blob JSON (%s): %w", blobID, err)
|
||||
}
|
||||
err = fs.db.Update(func(tx *bolt.Tx) error {
|
||||
layerBucket := tx.Bucket([]byte(layerBucket))
|
||||
err = layerBucket.Put([]byte(diffID), b)
|
||||
blobBucket := tx.Bucket([]byte(blobBucket))
|
||||
err = blobBucket.Put([]byte(blobID), b)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("unable to store layer information in cache (%s): %w", diffID, err)
|
||||
return xerrors.Errorf("unable to store blob information in cache (%s): %w", blobID, err)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
@@ -123,35 +137,37 @@ func (fs FSCache) PutLayer(diffID string, layerInfo types.LayerInfo) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (fs FSCache) GetImage(imageID string) (types.ImageInfo, error) {
|
||||
// GetArtifact gets artifact information such as image metadata from local cache
|
||||
func (fs FSCache) GetArtifact(artifactID string) (types.ArtifactInfo, error) {
|
||||
var blob []byte
|
||||
err := fs.db.View(func(tx *bolt.Tx) error {
|
||||
imageBucket := tx.Bucket([]byte(imageBucket))
|
||||
blob = imageBucket.Get([]byte(imageID))
|
||||
artifactBucket := tx.Bucket([]byte(artifactBucket))
|
||||
blob = artifactBucket.Get([]byte(artifactID))
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return types.ImageInfo{}, xerrors.Errorf("DB error: %w", err)
|
||||
return types.ArtifactInfo{}, xerrors.Errorf("DB error: %w", err)
|
||||
}
|
||||
|
||||
var info types.ImageInfo
|
||||
var info types.ArtifactInfo
|
||||
if err := json.Unmarshal(blob, &info); err != nil {
|
||||
return types.ImageInfo{}, xerrors.Errorf("JSON unmarshal error: %w", err)
|
||||
return types.ArtifactInfo{}, xerrors.Errorf("JSON unmarshal error: %w", err)
|
||||
}
|
||||
return info, nil
|
||||
}
|
||||
|
||||
func (fs FSCache) PutImage(imageID string, imageConfig types.ImageInfo) (err error) {
|
||||
b, err := json.Marshal(imageConfig)
|
||||
// PutArtifact stores artifact information such as image metadata in local cache
|
||||
func (fs FSCache) PutArtifact(artifactID string, artifactInfo types.ArtifactInfo) (err error) {
|
||||
b, err := json.Marshal(artifactInfo)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("unable to marshal image JSON (%s): %w", imageID, err)
|
||||
return xerrors.Errorf("unable to marshal artifact JSON (%s): %w", artifactID, err)
|
||||
}
|
||||
|
||||
err = fs.db.Update(func(tx *bolt.Tx) error {
|
||||
imageBucket := tx.Bucket([]byte(imageBucket))
|
||||
err = imageBucket.Put([]byte(imageID), b)
|
||||
artifactBucket := tx.Bucket([]byte(artifactBucket))
|
||||
err = artifactBucket.Put([]byte(artifactID), b)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("unable to store image information in cache (%s): %w", imageID, err)
|
||||
return xerrors.Errorf("unable to store artifact information in cache (%s): %w", artifactID, err)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
@@ -161,20 +177,21 @@ func (fs FSCache) PutImage(imageID string, imageConfig types.ImageInfo) (err err
|
||||
return nil
|
||||
}
|
||||
|
||||
func (fs FSCache) MissingLayers(imageID string, layerIDs []string) (bool, []string, error) {
|
||||
var missingImage bool
|
||||
var missingLayerIDs []string
|
||||
// MissingBlobs returns missing blob IDs such as layer IDs
|
||||
func (fs FSCache) MissingBlobs(artifactID string, blobIDs []string) (bool, []string, error) {
|
||||
var missingArtifact bool
|
||||
var missingBlobIDs []string
|
||||
err := fs.db.View(func(tx *bolt.Tx) error {
|
||||
layerBucket := tx.Bucket([]byte(layerBucket))
|
||||
for _, layerID := range layerIDs {
|
||||
layerInfo, err := fs.getLayer(layerBucket, layerID)
|
||||
blobBucket := tx.Bucket([]byte(blobBucket))
|
||||
for _, blobID := range blobIDs {
|
||||
blobInfo, err := fs.getBlob(blobBucket, blobID)
|
||||
if err != nil {
|
||||
// error means cache missed layer info
|
||||
missingLayerIDs = append(missingLayerIDs, layerID)
|
||||
// error means cache missed blob info
|
||||
missingBlobIDs = append(missingBlobIDs, blobID)
|
||||
continue
|
||||
}
|
||||
if layerInfo.SchemaVersion != types.LayerJSONSchemaVersion {
|
||||
missingLayerIDs = append(missingLayerIDs, layerID)
|
||||
if blobInfo.SchemaVersion != types.BlobJSONSchemaVersion {
|
||||
missingBlobIDs = append(missingBlobIDs, blobID)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
@@ -183,18 +200,19 @@ func (fs FSCache) MissingLayers(imageID string, layerIDs []string) (bool, []stri
|
||||
return false, nil, xerrors.Errorf("DB error: %w", err)
|
||||
}
|
||||
|
||||
// get image info
|
||||
imageInfo, err := fs.GetImage(imageID)
|
||||
// get artifact info
|
||||
artifactInfo, err := fs.GetArtifact(artifactID)
|
||||
if err != nil {
|
||||
// error means cache missed image info
|
||||
return true, missingLayerIDs, nil
|
||||
// error means cache missed artifact info
|
||||
return true, missingBlobIDs, nil
|
||||
}
|
||||
if imageInfo.SchemaVersion != types.ImageJSONSchemaVersion {
|
||||
missingImage = true
|
||||
if artifactInfo.SchemaVersion != types.ArtifactJSONSchemaVersion {
|
||||
missingArtifact = true
|
||||
}
|
||||
return missingImage, missingLayerIDs, nil
|
||||
return missingArtifact, missingBlobIDs, nil
|
||||
}
|
||||
|
||||
// Close closes the database
|
||||
func (fs FSCache) Close() error {
|
||||
if err := fs.db.Close(); err != nil {
|
||||
return xerrors.Errorf("unable to close DB: %w", err)
|
||||
@@ -202,6 +220,7 @@ func (fs FSCache) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Clear removes the database
|
||||
func (fs FSCache) Clear() error {
|
||||
if err := fs.Close(); err != nil {
|
||||
return err
|
||||
|
||||
26
cache/cache_test.go
vendored
26
cache/cache_test.go
vendored
@@ -71,7 +71,7 @@ func TestFSCache_GetLayer(t *testing.T) {
|
||||
name string
|
||||
dbPath string
|
||||
args args
|
||||
want types.LayerInfo
|
||||
want types.BlobInfo
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
@@ -80,7 +80,7 @@ func TestFSCache_GetLayer(t *testing.T) {
|
||||
args: args{
|
||||
layerID: "sha256:24df0d4e20c0f42d3703bf1f1db2bdd77346c7956f74f423603d651e8e5ae8a7",
|
||||
},
|
||||
want: types.LayerInfo{
|
||||
want: types.BlobInfo{
|
||||
SchemaVersion: 2,
|
||||
OS: &types.OS{
|
||||
Family: "alpine",
|
||||
@@ -107,7 +107,7 @@ func TestFSCache_GetLayer(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
defer fs.Clear()
|
||||
|
||||
got, err := fs.GetLayer(tt.args.layerID)
|
||||
got, err := fs.GetBlob(tt.args.layerID)
|
||||
assert.Equal(t, tt.wantErr, err != nil, err)
|
||||
assert.Equal(t, tt.want, got)
|
||||
})
|
||||
@@ -121,7 +121,7 @@ func TestFSCache_PutLayer(t *testing.T) {
|
||||
}
|
||||
type args struct {
|
||||
diffID string
|
||||
layerInfo types.LayerInfo
|
||||
layerInfo types.BlobInfo
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
@@ -135,7 +135,7 @@ func TestFSCache_PutLayer(t *testing.T) {
|
||||
name: "happy path",
|
||||
args: args{
|
||||
diffID: "sha256:24df0d4e20c0f42d3703bf1f1db2bdd77346c7956f74f423603d651e8e5ae8a7",
|
||||
layerInfo: types.LayerInfo{
|
||||
layerInfo: types.BlobInfo{
|
||||
SchemaVersion: 1,
|
||||
OS: &types.OS{
|
||||
Family: "alpine",
|
||||
@@ -157,7 +157,7 @@ func TestFSCache_PutLayer(t *testing.T) {
|
||||
name: "happy path: different decompressed layer ID",
|
||||
args: args{
|
||||
diffID: "sha256:dffd9992ca398466a663c87c92cfea2a2db0ae0cf33fcb99da60eec52addbfc5",
|
||||
layerInfo: types.LayerInfo{
|
||||
layerInfo: types.BlobInfo{
|
||||
SchemaVersion: 1,
|
||||
Digest: "sha256:dffd9992ca398466a663c87c92cfea2a2db0ae0cf33fcb99da60eec52addbfc5",
|
||||
DiffID: "sha256:dab15cac9ebd43beceeeda3ce95c574d6714ed3d3969071caead678c065813ec",
|
||||
@@ -270,7 +270,7 @@ func TestFSCache_PutLayer(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
defer fs.Clear()
|
||||
|
||||
err = fs.PutLayer(tt.args.diffID, tt.args.layerInfo)
|
||||
err = fs.PutBlob(tt.args.diffID, tt.args.layerInfo)
|
||||
if tt.wantErr != "" {
|
||||
require.NotNil(t, err)
|
||||
assert.Contains(t, err.Error(), tt.wantErr, tt.name)
|
||||
@@ -280,7 +280,7 @@ func TestFSCache_PutLayer(t *testing.T) {
|
||||
}
|
||||
|
||||
fs.db.View(func(tx *bolt.Tx) error {
|
||||
layerBucket := tx.Bucket([]byte(layerBucket))
|
||||
layerBucket := tx.Bucket([]byte(blobBucket))
|
||||
b := layerBucket.Get([]byte(tt.args.diffID))
|
||||
assert.JSONEq(t, tt.want, string(b))
|
||||
|
||||
@@ -293,7 +293,7 @@ func TestFSCache_PutLayer(t *testing.T) {
|
||||
func TestFSCache_PutImage(t *testing.T) {
|
||||
type args struct {
|
||||
imageID string
|
||||
imageConfig types.ImageInfo
|
||||
imageConfig types.ArtifactInfo
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
@@ -305,7 +305,7 @@ func TestFSCache_PutImage(t *testing.T) {
|
||||
name: "happy path",
|
||||
args: args{
|
||||
imageID: "sha256:58701fd185bda36cab0557bb6438661831267aa4a9e0b54211c4d5317a48aff4",
|
||||
imageConfig: types.ImageInfo{
|
||||
imageConfig: types.ArtifactInfo{
|
||||
SchemaVersion: 1,
|
||||
Architecture: "amd64",
|
||||
Created: time.Date(2020, 1, 2, 3, 4, 5, 0, time.UTC),
|
||||
@@ -347,7 +347,7 @@ func TestFSCache_PutImage(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
//defer fs.Clear()
|
||||
|
||||
err = fs.PutImage(tt.args.imageID, tt.args.imageConfig)
|
||||
err = fs.PutArtifact(tt.args.imageID, tt.args.imageConfig)
|
||||
if tt.wantErr != "" {
|
||||
require.NotNil(t, err)
|
||||
assert.Contains(t, err.Error(), tt.wantErr, tt.name)
|
||||
@@ -358,7 +358,7 @@ func TestFSCache_PutImage(t *testing.T) {
|
||||
|
||||
fs.db.View(func(tx *bolt.Tx) error {
|
||||
// check decompressedDigestBucket
|
||||
imageBucket := tx.Bucket([]byte(imageBucket))
|
||||
imageBucket := tx.Bucket([]byte(artifactBucket))
|
||||
b := imageBucket.Get([]byte(tt.args.imageID))
|
||||
assert.JSONEq(t, tt.want, string(b))
|
||||
|
||||
@@ -452,7 +452,7 @@ func TestFSCache_MissingLayers(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
defer fs.Clear()
|
||||
|
||||
gotMissingImage, gotMissingLayerIDs, err := fs.MissingLayers(tt.args.imageID, tt.args.layerIDs)
|
||||
gotMissingImage, gotMissingLayerIDs, err := fs.MissingBlobs(tt.args.imageID, tt.args.layerIDs)
|
||||
if tt.wantErr != "" {
|
||||
require.NotNil(t, err, tt.name)
|
||||
assert.Contains(t, err.Error(), tt.wantErr, tt.name)
|
||||
|
||||
184
cache/mock_artifact_cache.go
vendored
Normal file
184
cache/mock_artifact_cache.go
vendored
Normal file
@@ -0,0 +1,184 @@
|
||||
// Code generated by mockery v1.0.0. DO NOT EDIT.
|
||||
|
||||
package cache
|
||||
|
||||
import (
|
||||
types "github.com/aquasecurity/fanal/types"
|
||||
mock "github.com/stretchr/testify/mock"
|
||||
)
|
||||
|
||||
// MockArtifactCache is an autogenerated mock type for the ArtifactCache type
|
||||
type MockArtifactCache struct {
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
type ArtifactCacheMissingBlobsArgs struct {
|
||||
ArtifactID string
|
||||
ArtifactIDAnything bool
|
||||
BlobIDs []string
|
||||
BlobIDsAnything bool
|
||||
}
|
||||
|
||||
type ArtifactCacheMissingBlobsReturns struct {
|
||||
MissingArtifact bool
|
||||
MissingBlobIDs []string
|
||||
Err error
|
||||
}
|
||||
|
||||
type ArtifactCacheMissingBlobsExpectation struct {
|
||||
Args ArtifactCacheMissingBlobsArgs
|
||||
Returns ArtifactCacheMissingBlobsReturns
|
||||
}
|
||||
|
||||
func (_m *MockArtifactCache) ApplyMissingBlobsExpectation(e ArtifactCacheMissingBlobsExpectation) {
|
||||
var args []interface{}
|
||||
if e.Args.ArtifactIDAnything {
|
||||
args = append(args, mock.Anything)
|
||||
} else {
|
||||
args = append(args, e.Args.ArtifactID)
|
||||
}
|
||||
if e.Args.BlobIDsAnything {
|
||||
args = append(args, mock.Anything)
|
||||
} else {
|
||||
args = append(args, e.Args.BlobIDs)
|
||||
}
|
||||
_m.On("MissingBlobs", args...).Return(e.Returns.MissingArtifact, e.Returns.MissingBlobIDs, e.Returns.Err)
|
||||
}
|
||||
|
||||
func (_m *MockArtifactCache) ApplyMissingBlobsExpectations(expectations []ArtifactCacheMissingBlobsExpectation) {
|
||||
for _, e := range expectations {
|
||||
_m.ApplyMissingBlobsExpectation(e)
|
||||
}
|
||||
}
|
||||
|
||||
// MissingBlobs provides a mock function with given fields: artifactID, blobIDs
|
||||
func (_m *MockArtifactCache) MissingBlobs(artifactID string, blobIDs []string) (bool, []string, error) {
|
||||
ret := _m.Called(artifactID, blobIDs)
|
||||
|
||||
var r0 bool
|
||||
if rf, ok := ret.Get(0).(func(string, []string) bool); ok {
|
||||
r0 = rf(artifactID, blobIDs)
|
||||
} else {
|
||||
r0 = ret.Get(0).(bool)
|
||||
}
|
||||
|
||||
var r1 []string
|
||||
if rf, ok := ret.Get(1).(func(string, []string) []string); ok {
|
||||
r1 = rf(artifactID, blobIDs)
|
||||
} else {
|
||||
if ret.Get(1) != nil {
|
||||
r1 = ret.Get(1).([]string)
|
||||
}
|
||||
}
|
||||
|
||||
var r2 error
|
||||
if rf, ok := ret.Get(2).(func(string, []string) error); ok {
|
||||
r2 = rf(artifactID, blobIDs)
|
||||
} else {
|
||||
r2 = ret.Error(2)
|
||||
}
|
||||
|
||||
return r0, r1, r2
|
||||
}
|
||||
|
||||
type ArtifactCachePutArtifactArgs struct {
|
||||
ArtifactID string
|
||||
ArtifactIDAnything bool
|
||||
ArtifactInfo types.ArtifactInfo
|
||||
ArtifactInfoAnything bool
|
||||
}
|
||||
|
||||
type ArtifactCachePutArtifactReturns struct {
|
||||
Err error
|
||||
}
|
||||
|
||||
type ArtifactCachePutArtifactExpectation struct {
|
||||
Args ArtifactCachePutArtifactArgs
|
||||
Returns ArtifactCachePutArtifactReturns
|
||||
}
|
||||
|
||||
func (_m *MockArtifactCache) ApplyPutArtifactExpectation(e ArtifactCachePutArtifactExpectation) {
|
||||
var args []interface{}
|
||||
if e.Args.ArtifactIDAnything {
|
||||
args = append(args, mock.Anything)
|
||||
} else {
|
||||
args = append(args, e.Args.ArtifactID)
|
||||
}
|
||||
if e.Args.ArtifactInfoAnything {
|
||||
args = append(args, mock.Anything)
|
||||
} else {
|
||||
args = append(args, e.Args.ArtifactInfo)
|
||||
}
|
||||
_m.On("PutArtifact", args...).Return(e.Returns.Err)
|
||||
}
|
||||
|
||||
func (_m *MockArtifactCache) ApplyPutArtifactExpectations(expectations []ArtifactCachePutArtifactExpectation) {
|
||||
for _, e := range expectations {
|
||||
_m.ApplyPutArtifactExpectation(e)
|
||||
}
|
||||
}
|
||||
|
||||
// PutArtifact provides a mock function with given fields: artifactID, artifactInfo
|
||||
func (_m *MockArtifactCache) PutArtifact(artifactID string, artifactInfo types.ArtifactInfo) error {
|
||||
ret := _m.Called(artifactID, artifactInfo)
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(string, types.ArtifactInfo) error); ok {
|
||||
r0 = rf(artifactID, artifactInfo)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
type ArtifactCachePutBlobArgs struct {
|
||||
BlobID string
|
||||
BlobIDAnything bool
|
||||
BlobInfo types.BlobInfo
|
||||
BlobInfoAnything bool
|
||||
}
|
||||
|
||||
type ArtifactCachePutBlobReturns struct {
|
||||
Err error
|
||||
}
|
||||
|
||||
type ArtifactCachePutBlobExpectation struct {
|
||||
Args ArtifactCachePutBlobArgs
|
||||
Returns ArtifactCachePutBlobReturns
|
||||
}
|
||||
|
||||
func (_m *MockArtifactCache) ApplyPutBlobExpectation(e ArtifactCachePutBlobExpectation) {
|
||||
var args []interface{}
|
||||
if e.Args.BlobIDAnything {
|
||||
args = append(args, mock.Anything)
|
||||
} else {
|
||||
args = append(args, e.Args.BlobID)
|
||||
}
|
||||
if e.Args.BlobInfoAnything {
|
||||
args = append(args, mock.Anything)
|
||||
} else {
|
||||
args = append(args, e.Args.BlobInfo)
|
||||
}
|
||||
_m.On("PutBlob", args...).Return(e.Returns.Err)
|
||||
}
|
||||
|
||||
func (_m *MockArtifactCache) ApplyPutBlobExpectations(expectations []ArtifactCachePutBlobExpectation) {
|
||||
for _, e := range expectations {
|
||||
_m.ApplyPutBlobExpectation(e)
|
||||
}
|
||||
}
|
||||
|
||||
// PutBlob provides a mock function with given fields: blobID, blobInfo
|
||||
func (_m *MockArtifactCache) PutBlob(blobID string, blobInfo types.BlobInfo) error {
|
||||
ret := _m.Called(blobID, blobInfo)
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(string, types.BlobInfo) error); ok {
|
||||
r0 = rf(blobID, blobInfo)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
286
cache/mock_cache.go
vendored
286
cache/mock_cache.go
vendored
@@ -2,8 +2,10 @@
|
||||
|
||||
package cache
|
||||
|
||||
import mock "github.com/stretchr/testify/mock"
|
||||
import types "github.com/aquasecurity/fanal/types"
|
||||
import (
|
||||
types "github.com/aquasecurity/fanal/types"
|
||||
mock "github.com/stretchr/testify/mock"
|
||||
)
|
||||
|
||||
// MockCache is an autogenerated mock type for the Cache type
|
||||
type MockCache struct {
|
||||
@@ -43,51 +45,84 @@ func (_m *MockCache) Clear() error {
|
||||
return r0
|
||||
}
|
||||
|
||||
type CacheGetImageArgs struct {
|
||||
ImageID string
|
||||
ImageIDAnything bool
|
||||
type CacheCloseReturns struct {
|
||||
Err error
|
||||
}
|
||||
|
||||
type CacheGetImageReturns struct {
|
||||
ImageConfig types.ImageInfo
|
||||
Err error
|
||||
type CacheCloseExpectation struct {
|
||||
Returns CacheCloseReturns
|
||||
}
|
||||
|
||||
type CacheGetImageExpectation struct {
|
||||
Args CacheGetImageArgs
|
||||
Returns CacheGetImageReturns
|
||||
}
|
||||
|
||||
func (_m *MockCache) ApplyGetImageExpectation(e CacheGetImageExpectation) {
|
||||
func (_m *MockCache) ApplyCloseExpectation(e CacheCloseExpectation) {
|
||||
var args []interface{}
|
||||
if e.Args.ImageIDAnything {
|
||||
_m.On("Close", args...).Return(e.Returns.Err)
|
||||
}
|
||||
|
||||
func (_m *MockCache) ApplyCloseExpectations(expectations []CacheCloseExpectation) {
|
||||
for _, e := range expectations {
|
||||
_m.ApplyCloseExpectation(e)
|
||||
}
|
||||
}
|
||||
|
||||
// Close provides a mock function with given fields:
|
||||
func (_m *MockCache) Close() error {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func() error); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
type CacheGetArtifactArgs struct {
|
||||
ArtifactID string
|
||||
ArtifactIDAnything bool
|
||||
}
|
||||
|
||||
type CacheGetArtifactReturns struct {
|
||||
ArtifactInfo types.ArtifactInfo
|
||||
Err error
|
||||
}
|
||||
|
||||
type CacheGetArtifactExpectation struct {
|
||||
Args CacheGetArtifactArgs
|
||||
Returns CacheGetArtifactReturns
|
||||
}
|
||||
|
||||
func (_m *MockCache) ApplyGetArtifactExpectation(e CacheGetArtifactExpectation) {
|
||||
var args []interface{}
|
||||
if e.Args.ArtifactIDAnything {
|
||||
args = append(args, mock.Anything)
|
||||
} else {
|
||||
args = append(args, e.Args.ImageID)
|
||||
args = append(args, e.Args.ArtifactID)
|
||||
}
|
||||
_m.On("GetImage", args...).Return(e.Returns.ImageConfig, e.Returns.Err)
|
||||
_m.On("GetArtifact", args...).Return(e.Returns.ArtifactInfo, e.Returns.Err)
|
||||
}
|
||||
|
||||
func (_m *MockCache) ApplyGetImageExpectations(expectations []CacheGetImageExpectation) {
|
||||
func (_m *MockCache) ApplyGetArtifactExpectations(expectations []CacheGetArtifactExpectation) {
|
||||
for _, e := range expectations {
|
||||
_m.ApplyGetImageExpectation(e)
|
||||
_m.ApplyGetArtifactExpectation(e)
|
||||
}
|
||||
}
|
||||
|
||||
// GetImage provides a mock function with given fields: imageID
|
||||
func (_m *MockCache) GetImage(imageID string) (types.ImageInfo, error) {
|
||||
ret := _m.Called(imageID)
|
||||
// GetArtifact provides a mock function with given fields: artifactID
|
||||
func (_m *MockCache) GetArtifact(artifactID string) (types.ArtifactInfo, error) {
|
||||
ret := _m.Called(artifactID)
|
||||
|
||||
var r0 types.ImageInfo
|
||||
if rf, ok := ret.Get(0).(func(string) types.ImageInfo); ok {
|
||||
r0 = rf(imageID)
|
||||
var r0 types.ArtifactInfo
|
||||
if rf, ok := ret.Get(0).(func(string) types.ArtifactInfo); ok {
|
||||
r0 = rf(artifactID)
|
||||
} else {
|
||||
r0 = ret.Get(0).(types.ImageInfo)
|
||||
r0 = ret.Get(0).(types.ArtifactInfo)
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(string) error); ok {
|
||||
r1 = rf(imageID)
|
||||
r1 = rf(artifactID)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
@@ -95,103 +130,111 @@ func (_m *MockCache) GetImage(imageID string) (types.ImageInfo, error) {
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
type CacheGetLayerArgs struct {
|
||||
LayerID string
|
||||
LayerIDAnything bool
|
||||
type CacheGetBlobArgs struct {
|
||||
BlobID string
|
||||
BlobIDAnything bool
|
||||
}
|
||||
|
||||
type CacheGetLayerReturns struct {
|
||||
LayerInfo types.LayerInfo
|
||||
type CacheGetBlobReturns struct {
|
||||
BlobInfo types.BlobInfo
|
||||
Err error
|
||||
}
|
||||
|
||||
type CacheGetLayerExpectation struct {
|
||||
Args CacheGetLayerArgs
|
||||
Returns CacheGetLayerReturns
|
||||
type CacheGetBlobExpectation struct {
|
||||
Args CacheGetBlobArgs
|
||||
Returns CacheGetBlobReturns
|
||||
}
|
||||
|
||||
func (_m *MockCache) ApplyGetLayerExpectation(e CacheGetLayerExpectation) {
|
||||
func (_m *MockCache) ApplyGetBlobExpectation(e CacheGetBlobExpectation) {
|
||||
var args []interface{}
|
||||
if e.Args.LayerIDAnything {
|
||||
if e.Args.BlobIDAnything {
|
||||
args = append(args, mock.Anything)
|
||||
} else {
|
||||
args = append(args, e.Args.LayerID)
|
||||
args = append(args, e.Args.BlobID)
|
||||
}
|
||||
_m.On("GetLayer", args...).Return(e.Returns.LayerInfo)
|
||||
_m.On("GetBlob", args...).Return(e.Returns.BlobInfo, e.Returns.Err)
|
||||
}
|
||||
|
||||
func (_m *MockCache) ApplyGetLayerExpectations(expectations []CacheGetLayerExpectation) {
|
||||
func (_m *MockCache) ApplyGetBlobExpectations(expectations []CacheGetBlobExpectation) {
|
||||
for _, e := range expectations {
|
||||
_m.ApplyGetLayerExpectation(e)
|
||||
_m.ApplyGetBlobExpectation(e)
|
||||
}
|
||||
}
|
||||
|
||||
// GetLayer provides a mock function with given fields: layerID
|
||||
func (_m *MockCache) GetLayer(layerID string) types.LayerInfo {
|
||||
ret := _m.Called(layerID)
|
||||
// GetBlob provides a mock function with given fields: blobID
|
||||
func (_m *MockCache) GetBlob(blobID string) (types.BlobInfo, error) {
|
||||
ret := _m.Called(blobID)
|
||||
|
||||
var r0 types.LayerInfo
|
||||
if rf, ok := ret.Get(0).(func(string) types.LayerInfo); ok {
|
||||
r0 = rf(layerID)
|
||||
var r0 types.BlobInfo
|
||||
if rf, ok := ret.Get(0).(func(string) types.BlobInfo); ok {
|
||||
r0 = rf(blobID)
|
||||
} else {
|
||||
r0 = ret.Get(0).(types.LayerInfo)
|
||||
r0 = ret.Get(0).(types.BlobInfo)
|
||||
}
|
||||
|
||||
return r0
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(string) error); ok {
|
||||
r1 = rf(blobID)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
type CacheMissingLayersArgs struct {
|
||||
ImageID string
|
||||
ImageIDAnything bool
|
||||
LayerIDs []string
|
||||
LayerIDsAnything bool
|
||||
type CacheMissingBlobsArgs struct {
|
||||
ArtifactID string
|
||||
ArtifactIDAnything bool
|
||||
BlobIDs []string
|
||||
BlobIDsAnything bool
|
||||
}
|
||||
|
||||
type CacheMissingLayersReturns struct {
|
||||
MissingImage bool
|
||||
MissingLayerIDs []string
|
||||
type CacheMissingBlobsReturns struct {
|
||||
MissingArtifact bool
|
||||
MissingBlobIDs []string
|
||||
Err error
|
||||
}
|
||||
|
||||
type CacheMissingLayersExpectation struct {
|
||||
Args CacheMissingLayersArgs
|
||||
Returns CacheMissingLayersReturns
|
||||
type CacheMissingBlobsExpectation struct {
|
||||
Args CacheMissingBlobsArgs
|
||||
Returns CacheMissingBlobsReturns
|
||||
}
|
||||
|
||||
func (_m *MockCache) ApplyMissingLayersExpectation(e CacheMissingLayersExpectation) {
|
||||
func (_m *MockCache) ApplyMissingBlobsExpectation(e CacheMissingBlobsExpectation) {
|
||||
var args []interface{}
|
||||
if e.Args.ImageIDAnything {
|
||||
if e.Args.ArtifactIDAnything {
|
||||
args = append(args, mock.Anything)
|
||||
} else {
|
||||
args = append(args, e.Args.ImageID)
|
||||
args = append(args, e.Args.ArtifactID)
|
||||
}
|
||||
if e.Args.LayerIDsAnything {
|
||||
if e.Args.BlobIDsAnything {
|
||||
args = append(args, mock.Anything)
|
||||
} else {
|
||||
args = append(args, e.Args.LayerIDs)
|
||||
args = append(args, e.Args.BlobIDs)
|
||||
}
|
||||
_m.On("MissingLayers", args...).Return(e.Returns.MissingImage, e.Returns.MissingLayerIDs, e.Returns.Err)
|
||||
_m.On("MissingBlobs", args...).Return(e.Returns.MissingArtifact, e.Returns.MissingBlobIDs, e.Returns.Err)
|
||||
}
|
||||
|
||||
func (_m *MockCache) ApplyMissingLayersExpectations(expectations []CacheMissingLayersExpectation) {
|
||||
func (_m *MockCache) ApplyMissingBlobsExpectations(expectations []CacheMissingBlobsExpectation) {
|
||||
for _, e := range expectations {
|
||||
_m.ApplyMissingLayersExpectation(e)
|
||||
_m.ApplyMissingBlobsExpectation(e)
|
||||
}
|
||||
}
|
||||
|
||||
// MissingLayers provides a mock function with given fields: imageID, layerIDs
|
||||
func (_m *MockCache) MissingLayers(imageID string, layerIDs []string) (bool, []string, error) {
|
||||
ret := _m.Called(imageID, layerIDs)
|
||||
// MissingBlobs provides a mock function with given fields: artifactID, blobIDs
|
||||
func (_m *MockCache) MissingBlobs(artifactID string, blobIDs []string) (bool, []string, error) {
|
||||
ret := _m.Called(artifactID, blobIDs)
|
||||
|
||||
var r0 bool
|
||||
if rf, ok := ret.Get(0).(func(string, []string) bool); ok {
|
||||
r0 = rf(imageID, layerIDs)
|
||||
r0 = rf(artifactID, blobIDs)
|
||||
} else {
|
||||
r0 = ret.Get(0).(bool)
|
||||
}
|
||||
|
||||
var r1 []string
|
||||
if rf, ok := ret.Get(1).(func(string, []string) []string); ok {
|
||||
r1 = rf(imageID, layerIDs)
|
||||
r1 = rf(artifactID, blobIDs)
|
||||
} else {
|
||||
if ret.Get(1) != nil {
|
||||
r1 = ret.Get(1).([]string)
|
||||
@@ -200,7 +243,7 @@ func (_m *MockCache) MissingLayers(imageID string, layerIDs []string) (bool, []s
|
||||
|
||||
var r2 error
|
||||
if rf, ok := ret.Get(2).(func(string, []string) error); ok {
|
||||
r2 = rf(imageID, layerIDs)
|
||||
r2 = rf(artifactID, blobIDs)
|
||||
} else {
|
||||
r2 = ret.Error(2)
|
||||
}
|
||||
@@ -208,50 +251,50 @@ func (_m *MockCache) MissingLayers(imageID string, layerIDs []string) (bool, []s
|
||||
return r0, r1, r2
|
||||
}
|
||||
|
||||
type CachePutImageArgs struct {
|
||||
ImageID string
|
||||
ImageIDAnything bool
|
||||
ImageConfig types.ImageInfo
|
||||
ImageConfigAnything bool
|
||||
type CachePutArtifactArgs struct {
|
||||
ArtifactID string
|
||||
ArtifactIDAnything bool
|
||||
ArtifactInfo types.ArtifactInfo
|
||||
ArtifactInfoAnything bool
|
||||
}
|
||||
|
||||
type CachePutImageReturns struct {
|
||||
type CachePutArtifactReturns struct {
|
||||
Err error
|
||||
}
|
||||
|
||||
type CachePutImageExpectation struct {
|
||||
Args CachePutImageArgs
|
||||
Returns CachePutImageReturns
|
||||
type CachePutArtifactExpectation struct {
|
||||
Args CachePutArtifactArgs
|
||||
Returns CachePutArtifactReturns
|
||||
}
|
||||
|
||||
func (_m *MockCache) ApplyPutImageExpectation(e CachePutImageExpectation) {
|
||||
func (_m *MockCache) ApplyPutArtifactExpectation(e CachePutArtifactExpectation) {
|
||||
var args []interface{}
|
||||
if e.Args.ImageIDAnything {
|
||||
if e.Args.ArtifactIDAnything {
|
||||
args = append(args, mock.Anything)
|
||||
} else {
|
||||
args = append(args, e.Args.ImageID)
|
||||
args = append(args, e.Args.ArtifactID)
|
||||
}
|
||||
if e.Args.ImageConfigAnything {
|
||||
if e.Args.ArtifactInfoAnything {
|
||||
args = append(args, mock.Anything)
|
||||
} else {
|
||||
args = append(args, e.Args.ImageConfig)
|
||||
args = append(args, e.Args.ArtifactInfo)
|
||||
}
|
||||
_m.On("PutImage", args...).Return(e.Returns.Err)
|
||||
_m.On("PutArtifact", args...).Return(e.Returns.Err)
|
||||
}
|
||||
|
||||
func (_m *MockCache) ApplyPutImageExpectations(expectations []CachePutImageExpectation) {
|
||||
func (_m *MockCache) ApplyPutArtifactExpectations(expectations []CachePutArtifactExpectation) {
|
||||
for _, e := range expectations {
|
||||
_m.ApplyPutImageExpectation(e)
|
||||
_m.ApplyPutArtifactExpectation(e)
|
||||
}
|
||||
}
|
||||
|
||||
// PutImage provides a mock function with given fields: imageID, imageConfig
|
||||
func (_m *MockCache) PutImage(imageID string, imageConfig types.ImageInfo) error {
|
||||
ret := _m.Called(imageID, imageConfig)
|
||||
// PutArtifact provides a mock function with given fields: artifactID, artifactInfo
|
||||
func (_m *MockCache) PutArtifact(artifactID string, artifactInfo types.ArtifactInfo) error {
|
||||
ret := _m.Called(artifactID, artifactInfo)
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(string, types.ImageInfo) error); ok {
|
||||
r0 = rf(imageID, imageConfig)
|
||||
if rf, ok := ret.Get(0).(func(string, types.ArtifactInfo) error); ok {
|
||||
r0 = rf(artifactID, artifactInfo)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
@@ -259,57 +302,50 @@ func (_m *MockCache) PutImage(imageID string, imageConfig types.ImageInfo) error
|
||||
return r0
|
||||
}
|
||||
|
||||
type CachePutLayerArgs struct {
|
||||
LayerID string
|
||||
LayerIDAnything bool
|
||||
DecompressedLayerID string
|
||||
DecompressedLayerIDAnything bool
|
||||
LayerInfo types.LayerInfo
|
||||
LayerInfoAnything bool
|
||||
type CachePutBlobArgs struct {
|
||||
BlobID string
|
||||
BlobIDAnything bool
|
||||
BlobInfo types.BlobInfo
|
||||
BlobInfoAnything bool
|
||||
}
|
||||
|
||||
type CachePutLayerReturns struct {
|
||||
type CachePutBlobReturns struct {
|
||||
Err error
|
||||
}
|
||||
|
||||
type CachePutLayerExpectation struct {
|
||||
Args CachePutLayerArgs
|
||||
Returns CachePutLayerReturns
|
||||
type CachePutBlobExpectation struct {
|
||||
Args CachePutBlobArgs
|
||||
Returns CachePutBlobReturns
|
||||
}
|
||||
|
||||
func (_m *MockCache) ApplyPutLayerExpectation(e CachePutLayerExpectation) {
|
||||
func (_m *MockCache) ApplyPutBlobExpectation(e CachePutBlobExpectation) {
|
||||
var args []interface{}
|
||||
if e.Args.LayerIDAnything {
|
||||
if e.Args.BlobIDAnything {
|
||||
args = append(args, mock.Anything)
|
||||
} else {
|
||||
args = append(args, e.Args.LayerID)
|
||||
args = append(args, e.Args.BlobID)
|
||||
}
|
||||
if e.Args.DecompressedLayerIDAnything {
|
||||
if e.Args.BlobInfoAnything {
|
||||
args = append(args, mock.Anything)
|
||||
} else {
|
||||
args = append(args, e.Args.DecompressedLayerID)
|
||||
args = append(args, e.Args.BlobInfo)
|
||||
}
|
||||
if e.Args.LayerInfoAnything {
|
||||
args = append(args, mock.Anything)
|
||||
} else {
|
||||
args = append(args, e.Args.LayerInfo)
|
||||
}
|
||||
_m.On("PutLayer", args...).Return(e.Returns.Err)
|
||||
_m.On("PutBlob", args...).Return(e.Returns.Err)
|
||||
}
|
||||
|
||||
func (_m *MockCache) ApplyPutLayerExpectations(expectations []CachePutLayerExpectation) {
|
||||
func (_m *MockCache) ApplyPutBlobExpectations(expectations []CachePutBlobExpectation) {
|
||||
for _, e := range expectations {
|
||||
_m.ApplyPutLayerExpectation(e)
|
||||
_m.ApplyPutBlobExpectation(e)
|
||||
}
|
||||
}
|
||||
|
||||
// PutLayer provides a mock function with given fields: layerID, decompressedLayerID, layerInfo
|
||||
func (_m *MockCache) PutLayer(layerID string, decompressedLayerID string, layerInfo types.LayerInfo) error {
|
||||
ret := _m.Called(layerID, decompressedLayerID, layerInfo)
|
||||
// PutBlob provides a mock function with given fields: blobID, blobInfo
|
||||
func (_m *MockCache) PutBlob(blobID string, blobInfo types.BlobInfo) error {
|
||||
ret := _m.Called(blobID, blobInfo)
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(string, string, types.LayerInfo) error); ok {
|
||||
r0 = rf(layerID, decompressedLayerID, layerInfo)
|
||||
if rf, ok := ret.Get(0).(func(string, types.BlobInfo) error); ok {
|
||||
r0 = rf(blobID, blobInfo)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
184
cache/mock_image_cache.go
vendored
184
cache/mock_image_cache.go
vendored
@@ -1,184 +0,0 @@
|
||||
// Code generated by mockery v1.0.0. DO NOT EDIT.
|
||||
|
||||
package cache
|
||||
|
||||
import (
|
||||
types "github.com/aquasecurity/fanal/types"
|
||||
mock "github.com/stretchr/testify/mock"
|
||||
)
|
||||
|
||||
// MockImageCache is an autogenerated mock type for the ImageCache type
|
||||
type MockImageCache struct {
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
type ImageCacheMissingLayersArgs struct {
|
||||
ImageID string
|
||||
ImageIDAnything bool
|
||||
LayerIDs []string
|
||||
LayerIDsAnything bool
|
||||
}
|
||||
|
||||
type ImageCacheMissingLayersReturns struct {
|
||||
MissingImage bool
|
||||
MissingLayerIDs []string
|
||||
Err error
|
||||
}
|
||||
|
||||
type ImageCacheMissingLayersExpectation struct {
|
||||
Args ImageCacheMissingLayersArgs
|
||||
Returns ImageCacheMissingLayersReturns
|
||||
}
|
||||
|
||||
func (_m *MockImageCache) ApplyMissingLayersExpectation(e ImageCacheMissingLayersExpectation) {
|
||||
var args []interface{}
|
||||
if e.Args.ImageIDAnything {
|
||||
args = append(args, mock.Anything)
|
||||
} else {
|
||||
args = append(args, e.Args.ImageID)
|
||||
}
|
||||
if e.Args.LayerIDsAnything {
|
||||
args = append(args, mock.Anything)
|
||||
} else {
|
||||
args = append(args, e.Args.LayerIDs)
|
||||
}
|
||||
_m.On("MissingLayers", args...).Return(e.Returns.MissingImage, e.Returns.MissingLayerIDs, e.Returns.Err)
|
||||
}
|
||||
|
||||
func (_m *MockImageCache) ApplyMissingLayersExpectations(expectations []ImageCacheMissingLayersExpectation) {
|
||||
for _, e := range expectations {
|
||||
_m.ApplyMissingLayersExpectation(e)
|
||||
}
|
||||
}
|
||||
|
||||
// MissingLayers provides a mock function with given fields: imageID, layerIDs
|
||||
func (_m *MockImageCache) MissingLayers(imageID string, layerIDs []string) (bool, []string, error) {
|
||||
ret := _m.Called(imageID, layerIDs)
|
||||
|
||||
var r0 bool
|
||||
if rf, ok := ret.Get(0).(func(string, []string) bool); ok {
|
||||
r0 = rf(imageID, layerIDs)
|
||||
} else {
|
||||
r0 = ret.Get(0).(bool)
|
||||
}
|
||||
|
||||
var r1 []string
|
||||
if rf, ok := ret.Get(1).(func(string, []string) []string); ok {
|
||||
r1 = rf(imageID, layerIDs)
|
||||
} else {
|
||||
if ret.Get(1) != nil {
|
||||
r1 = ret.Get(1).([]string)
|
||||
}
|
||||
}
|
||||
|
||||
var r2 error
|
||||
if rf, ok := ret.Get(2).(func(string, []string) error); ok {
|
||||
r2 = rf(imageID, layerIDs)
|
||||
} else {
|
||||
r2 = ret.Error(2)
|
||||
}
|
||||
|
||||
return r0, r1, r2
|
||||
}
|
||||
|
||||
type ImageCachePutImageArgs struct {
|
||||
ImageID string
|
||||
ImageIDAnything bool
|
||||
ImageInfo types.ImageInfo
|
||||
ImageInfoAnything bool
|
||||
}
|
||||
|
||||
type ImageCachePutImageReturns struct {
|
||||
Err error
|
||||
}
|
||||
|
||||
type ImageCachePutImageExpectation struct {
|
||||
Args ImageCachePutImageArgs
|
||||
Returns ImageCachePutImageReturns
|
||||
}
|
||||
|
||||
func (_m *MockImageCache) ApplyPutImageExpectation(e ImageCachePutImageExpectation) {
|
||||
var args []interface{}
|
||||
if e.Args.ImageIDAnything {
|
||||
args = append(args, mock.Anything)
|
||||
} else {
|
||||
args = append(args, e.Args.ImageID)
|
||||
}
|
||||
if e.Args.ImageInfoAnything {
|
||||
args = append(args, mock.Anything)
|
||||
} else {
|
||||
args = append(args, e.Args.ImageInfo)
|
||||
}
|
||||
_m.On("PutImage", args...).Return(e.Returns.Err)
|
||||
}
|
||||
|
||||
func (_m *MockImageCache) ApplyPutImageExpectations(expectations []ImageCachePutImageExpectation) {
|
||||
for _, e := range expectations {
|
||||
_m.ApplyPutImageExpectation(e)
|
||||
}
|
||||
}
|
||||
|
||||
// PutImage provides a mock function with given fields: imageID, imageInfo
|
||||
func (_m *MockImageCache) PutImage(imageID string, imageInfo types.ImageInfo) error {
|
||||
ret := _m.Called(imageID, imageInfo)
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(string, types.ImageInfo) error); ok {
|
||||
r0 = rf(imageID, imageInfo)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
type ImageCachePutLayerArgs struct {
|
||||
DiffID string
|
||||
DiffIDAnything bool
|
||||
LayerInfo types.LayerInfo
|
||||
LayerInfoAnything bool
|
||||
}
|
||||
|
||||
type ImageCachePutLayerReturns struct {
|
||||
Err error
|
||||
}
|
||||
|
||||
type ImageCachePutLayerExpectation struct {
|
||||
Args ImageCachePutLayerArgs
|
||||
Returns ImageCachePutLayerReturns
|
||||
}
|
||||
|
||||
func (_m *MockImageCache) ApplyPutLayerExpectation(e ImageCachePutLayerExpectation) {
|
||||
var args []interface{}
|
||||
if e.Args.DiffIDAnything {
|
||||
args = append(args, mock.Anything)
|
||||
} else {
|
||||
args = append(args, e.Args.DiffID)
|
||||
}
|
||||
if e.Args.LayerInfoAnything {
|
||||
args = append(args, mock.Anything)
|
||||
} else {
|
||||
args = append(args, e.Args.LayerInfo)
|
||||
}
|
||||
_m.On("PutLayer", args...).Return(e.Returns.Err)
|
||||
}
|
||||
|
||||
func (_m *MockImageCache) ApplyPutLayerExpectations(expectations []ImageCachePutLayerExpectation) {
|
||||
for _, e := range expectations {
|
||||
_m.ApplyPutLayerExpectation(e)
|
||||
}
|
||||
}
|
||||
|
||||
// PutLayer provides a mock function with given fields: diffID, layerInfo
|
||||
func (_m *MockImageCache) PutLayer(diffID string, layerInfo types.LayerInfo) error {
|
||||
ret := _m.Called(diffID, layerInfo)
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(string, types.LayerInfo) error); ok {
|
||||
r0 = rf(diffID, layerInfo)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
183
cache/mock_local_artifact_cache.go
vendored
Normal file
183
cache/mock_local_artifact_cache.go
vendored
Normal file
@@ -0,0 +1,183 @@
|
||||
// Code generated by mockery v1.0.0. DO NOT EDIT.
|
||||
|
||||
package cache
|
||||
|
||||
import (
|
||||
types "github.com/aquasecurity/fanal/types"
|
||||
mock "github.com/stretchr/testify/mock"
|
||||
)
|
||||
|
||||
// MockLocalArtifactCache is an autogenerated mock type for the LocalArtifactCache type
|
||||
type MockLocalArtifactCache struct {
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
type LocalArtifactCacheClearReturns struct {
|
||||
Err error
|
||||
}
|
||||
|
||||
type LocalArtifactCacheClearExpectation struct {
|
||||
Returns LocalArtifactCacheClearReturns
|
||||
}
|
||||
|
||||
func (_m *MockLocalArtifactCache) ApplyClearExpectation(e LocalArtifactCacheClearExpectation) {
|
||||
var args []interface{}
|
||||
_m.On("Clear", args...).Return(e.Returns.Err)
|
||||
}
|
||||
|
||||
func (_m *MockLocalArtifactCache) ApplyClearExpectations(expectations []LocalArtifactCacheClearExpectation) {
|
||||
for _, e := range expectations {
|
||||
_m.ApplyClearExpectation(e)
|
||||
}
|
||||
}
|
||||
|
||||
// Clear provides a mock function with given fields:
|
||||
func (_m *MockLocalArtifactCache) Clear() error {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func() error); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
type LocalArtifactCacheCloseReturns struct {
|
||||
Err error
|
||||
}
|
||||
|
||||
type LocalArtifactCacheCloseExpectation struct {
|
||||
Returns LocalArtifactCacheCloseReturns
|
||||
}
|
||||
|
||||
func (_m *MockLocalArtifactCache) ApplyCloseExpectation(e LocalArtifactCacheCloseExpectation) {
|
||||
var args []interface{}
|
||||
_m.On("Close", args...).Return(e.Returns.Err)
|
||||
}
|
||||
|
||||
func (_m *MockLocalArtifactCache) ApplyCloseExpectations(expectations []LocalArtifactCacheCloseExpectation) {
|
||||
for _, e := range expectations {
|
||||
_m.ApplyCloseExpectation(e)
|
||||
}
|
||||
}
|
||||
|
||||
// Close provides a mock function with given fields:
|
||||
func (_m *MockLocalArtifactCache) Close() error {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func() error); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
type LocalArtifactCacheGetArtifactArgs struct {
|
||||
ArtifactID string
|
||||
ArtifactIDAnything bool
|
||||
}
|
||||
|
||||
type LocalArtifactCacheGetArtifactReturns struct {
|
||||
ArtifactInfo types.ArtifactInfo
|
||||
Err error
|
||||
}
|
||||
|
||||
type LocalArtifactCacheGetArtifactExpectation struct {
|
||||
Args LocalArtifactCacheGetArtifactArgs
|
||||
Returns LocalArtifactCacheGetArtifactReturns
|
||||
}
|
||||
|
||||
func (_m *MockLocalArtifactCache) ApplyGetArtifactExpectation(e LocalArtifactCacheGetArtifactExpectation) {
|
||||
var args []interface{}
|
||||
if e.Args.ArtifactIDAnything {
|
||||
args = append(args, mock.Anything)
|
||||
} else {
|
||||
args = append(args, e.Args.ArtifactID)
|
||||
}
|
||||
_m.On("GetArtifact", args...).Return(e.Returns.ArtifactInfo, e.Returns.Err)
|
||||
}
|
||||
|
||||
func (_m *MockLocalArtifactCache) ApplyGetArtifactExpectations(expectations []LocalArtifactCacheGetArtifactExpectation) {
|
||||
for _, e := range expectations {
|
||||
_m.ApplyGetArtifactExpectation(e)
|
||||
}
|
||||
}
|
||||
|
||||
// GetArtifact provides a mock function with given fields: artifactID
|
||||
func (_m *MockLocalArtifactCache) GetArtifact(artifactID string) (types.ArtifactInfo, error) {
|
||||
ret := _m.Called(artifactID)
|
||||
|
||||
var r0 types.ArtifactInfo
|
||||
if rf, ok := ret.Get(0).(func(string) types.ArtifactInfo); ok {
|
||||
r0 = rf(artifactID)
|
||||
} else {
|
||||
r0 = ret.Get(0).(types.ArtifactInfo)
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(string) error); ok {
|
||||
r1 = rf(artifactID)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
type LocalArtifactCacheGetBlobArgs struct {
|
||||
BlobID string
|
||||
BlobIDAnything bool
|
||||
}
|
||||
|
||||
type LocalArtifactCacheGetBlobReturns struct {
|
||||
BlobInfo types.BlobInfo
|
||||
Err error
|
||||
}
|
||||
|
||||
type LocalArtifactCacheGetBlobExpectation struct {
|
||||
Args LocalArtifactCacheGetBlobArgs
|
||||
Returns LocalArtifactCacheGetBlobReturns
|
||||
}
|
||||
|
||||
func (_m *MockLocalArtifactCache) ApplyGetBlobExpectation(e LocalArtifactCacheGetBlobExpectation) {
|
||||
var args []interface{}
|
||||
if e.Args.BlobIDAnything {
|
||||
args = append(args, mock.Anything)
|
||||
} else {
|
||||
args = append(args, e.Args.BlobID)
|
||||
}
|
||||
_m.On("GetBlob", args...).Return(e.Returns.BlobInfo, e.Returns.Err)
|
||||
}
|
||||
|
||||
func (_m *MockLocalArtifactCache) ApplyGetBlobExpectations(expectations []LocalArtifactCacheGetBlobExpectation) {
|
||||
for _, e := range expectations {
|
||||
_m.ApplyGetBlobExpectation(e)
|
||||
}
|
||||
}
|
||||
|
||||
// GetBlob provides a mock function with given fields: blobID
|
||||
func (_m *MockLocalArtifactCache) GetBlob(blobID string) (types.BlobInfo, error) {
|
||||
ret := _m.Called(blobID)
|
||||
|
||||
var r0 types.BlobInfo
|
||||
if rf, ok := ret.Get(0).(func(string) types.BlobInfo); ok {
|
||||
r0 = rf(blobID)
|
||||
} else {
|
||||
r0 = ret.Get(0).(types.BlobInfo)
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(string) error); ok {
|
||||
r1 = rf(blobID)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
183
cache/mock_local_image_cache.go
vendored
183
cache/mock_local_image_cache.go
vendored
@@ -1,183 +0,0 @@
|
||||
// Code generated by mockery v1.0.0. DO NOT EDIT.
|
||||
|
||||
package cache
|
||||
|
||||
import (
|
||||
types "github.com/aquasecurity/fanal/types"
|
||||
mock "github.com/stretchr/testify/mock"
|
||||
)
|
||||
|
||||
// MockLocalImageCache is an autogenerated mock type for the LocalImageCache type
|
||||
type MockLocalImageCache struct {
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
type LocalImageCacheClearReturns struct {
|
||||
Err error
|
||||
}
|
||||
|
||||
type LocalImageCacheClearExpectation struct {
|
||||
Returns LocalImageCacheClearReturns
|
||||
}
|
||||
|
||||
func (_m *MockLocalImageCache) ApplyClearExpectation(e LocalImageCacheClearExpectation) {
|
||||
var args []interface{}
|
||||
_m.On("Clear", args...).Return(e.Returns.Err)
|
||||
}
|
||||
|
||||
func (_m *MockLocalImageCache) ApplyClearExpectations(expectations []LocalImageCacheClearExpectation) {
|
||||
for _, e := range expectations {
|
||||
_m.ApplyClearExpectation(e)
|
||||
}
|
||||
}
|
||||
|
||||
// Clear provides a mock function with given fields:
|
||||
func (_m *MockLocalImageCache) Clear() error {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func() error); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
type LocalImageCacheCloseReturns struct {
|
||||
Err error
|
||||
}
|
||||
|
||||
type LocalImageCacheCloseExpectation struct {
|
||||
Returns LocalImageCacheCloseReturns
|
||||
}
|
||||
|
||||
func (_m *MockLocalImageCache) ApplyCloseExpectation(e LocalImageCacheCloseExpectation) {
|
||||
var args []interface{}
|
||||
_m.On("Close", args...).Return(e.Returns.Err)
|
||||
}
|
||||
|
||||
func (_m *MockLocalImageCache) ApplyCloseExpectations(expectations []LocalImageCacheCloseExpectation) {
|
||||
for _, e := range expectations {
|
||||
_m.ApplyCloseExpectation(e)
|
||||
}
|
||||
}
|
||||
|
||||
// Close provides a mock function with given fields:
|
||||
func (_m *MockLocalImageCache) Close() error {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func() error); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
type LocalImageCacheGetImageArgs struct {
|
||||
ImageID string
|
||||
ImageIDAnything bool
|
||||
}
|
||||
|
||||
type LocalImageCacheGetImageReturns struct {
|
||||
ImageInfo types.ImageInfo
|
||||
Err error
|
||||
}
|
||||
|
||||
type LocalImageCacheGetImageExpectation struct {
|
||||
Args LocalImageCacheGetImageArgs
|
||||
Returns LocalImageCacheGetImageReturns
|
||||
}
|
||||
|
||||
func (_m *MockLocalImageCache) ApplyGetImageExpectation(e LocalImageCacheGetImageExpectation) {
|
||||
var args []interface{}
|
||||
if e.Args.ImageIDAnything {
|
||||
args = append(args, mock.Anything)
|
||||
} else {
|
||||
args = append(args, e.Args.ImageID)
|
||||
}
|
||||
_m.On("GetImage", args...).Return(e.Returns.ImageInfo, e.Returns.Err)
|
||||
}
|
||||
|
||||
func (_m *MockLocalImageCache) ApplyGetImageExpectations(expectations []LocalImageCacheGetImageExpectation) {
|
||||
for _, e := range expectations {
|
||||
_m.ApplyGetImageExpectation(e)
|
||||
}
|
||||
}
|
||||
|
||||
// GetImage provides a mock function with given fields: imageID
|
||||
func (_m *MockLocalImageCache) GetImage(imageID string) (types.ImageInfo, error) {
|
||||
ret := _m.Called(imageID)
|
||||
|
||||
var r0 types.ImageInfo
|
||||
if rf, ok := ret.Get(0).(func(string) types.ImageInfo); ok {
|
||||
r0 = rf(imageID)
|
||||
} else {
|
||||
r0 = ret.Get(0).(types.ImageInfo)
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(string) error); ok {
|
||||
r1 = rf(imageID)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
type LocalImageCacheGetLayerArgs struct {
|
||||
DiffID string
|
||||
DiffIDAnything bool
|
||||
}
|
||||
|
||||
type LocalImageCacheGetLayerReturns struct {
|
||||
LayerInfo types.LayerInfo
|
||||
Err error
|
||||
}
|
||||
|
||||
type LocalImageCacheGetLayerExpectation struct {
|
||||
Args LocalImageCacheGetLayerArgs
|
||||
Returns LocalImageCacheGetLayerReturns
|
||||
}
|
||||
|
||||
func (_m *MockLocalImageCache) ApplyGetLayerExpectation(e LocalImageCacheGetLayerExpectation) {
|
||||
var args []interface{}
|
||||
if e.Args.DiffIDAnything {
|
||||
args = append(args, mock.Anything)
|
||||
} else {
|
||||
args = append(args, e.Args.DiffID)
|
||||
}
|
||||
_m.On("GetLayer", args...).Return(e.Returns.LayerInfo, e.Returns.Err)
|
||||
}
|
||||
|
||||
func (_m *MockLocalImageCache) ApplyGetLayerExpectations(expectations []LocalImageCacheGetLayerExpectation) {
|
||||
for _, e := range expectations {
|
||||
_m.ApplyGetLayerExpectation(e)
|
||||
}
|
||||
}
|
||||
|
||||
// GetLayer provides a mock function with given fields: diffID
|
||||
func (_m *MockLocalImageCache) GetLayer(diffID string) (types.LayerInfo, error) {
|
||||
ret := _m.Called(diffID)
|
||||
|
||||
var r0 types.LayerInfo
|
||||
if rf, ok := ret.Get(0).(func(string) types.LayerInfo); ok {
|
||||
r0 = rf(diffID)
|
||||
} else {
|
||||
r0 = ret.Get(0).(types.LayerInfo)
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(string) error); ok {
|
||||
r1 = rf(diffID)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
33
cache/s3.go
vendored
33
cache/s3.go
vendored
@@ -4,6 +4,7 @@ import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/aquasecurity/fanal/types"
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/session"
|
||||
@@ -36,19 +37,19 @@ func NewS3Cache(region string, bucketName string) (S3Cache, error) {
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (cache S3Cache) PutLayer(diffID string, layerInfo types.LayerInfo) error {
|
||||
func (cache S3Cache) PutLayer(diffID string, layerInfo types.BlobInfo) error {
|
||||
if _, err := v1.NewHash(diffID); err != nil {
|
||||
return xerrors.Errorf("invalid diffID (%s): %w", diffID, err)
|
||||
}
|
||||
key := fmt.Sprintf("%s/%s", layerBucket, diffID)
|
||||
key := fmt.Sprintf("%s/%s", blobBucket, diffID)
|
||||
if err := cache.put(key, layerInfo); err != nil {
|
||||
return xerrors.Errorf("unable to store layer information in cache (%s): %w", diffID, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cache S3Cache) PutImage(imageID string, imageConfig types.ImageInfo) (err error) {
|
||||
key := fmt.Sprintf("%s/%s", imageBucket, imageID)
|
||||
func (cache S3Cache) PutImage(imageID string, imageConfig types.ArtifactInfo) (err error) {
|
||||
key := fmt.Sprintf("%s/%s", artifactBucket, imageID)
|
||||
if err := cache.put(key, imageConfig); err != nil {
|
||||
return xerrors.Errorf("unable to store image information in cache (%s): %w", imageID, err)
|
||||
}
|
||||
@@ -79,39 +80,39 @@ func (cache S3Cache) put(key string, body interface{}) (err error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cache S3Cache) GetLayer(diffID string) (types.LayerInfo, error) {
|
||||
var layerInfo types.LayerInfo
|
||||
func (cache S3Cache) GetLayer(diffID string) (types.BlobInfo, error) {
|
||||
var layerInfo types.BlobInfo
|
||||
|
||||
buf := aws.NewWriteAtBuffer([]byte{})
|
||||
_, err := cache.downloader.Download(buf, &s3.GetObjectInput{
|
||||
Bucket: aws.String(cache.bucketName),
|
||||
Key: aws.String(fmt.Sprintf("%s/%s", layerBucket, diffID)), //TODO add prefix
|
||||
Key: aws.String(fmt.Sprintf("%s/%s", blobBucket, diffID)), //TODO add prefix
|
||||
})
|
||||
if err != nil {
|
||||
return types.LayerInfo{}, xerrors.Errorf("failed to get layer from the cache: %w", err)
|
||||
return types.BlobInfo{}, xerrors.Errorf("failed to get layer from the cache: %w", err)
|
||||
}
|
||||
err = json.Unmarshal(buf.Bytes(), &layerInfo)
|
||||
if err != nil {
|
||||
return types.LayerInfo{}, xerrors.Errorf("JSON unmarshal error: %w", err)
|
||||
return types.BlobInfo{}, xerrors.Errorf("JSON unmarshal error: %w", err)
|
||||
}
|
||||
|
||||
return layerInfo, nil
|
||||
}
|
||||
|
||||
func (cache S3Cache) GetImage(imageID string) (types.ImageInfo, error) {
|
||||
var info types.ImageInfo
|
||||
func (cache S3Cache) GetImage(imageID string) (types.ArtifactInfo, error) {
|
||||
var info types.ArtifactInfo
|
||||
|
||||
buf := aws.NewWriteAtBuffer([]byte{})
|
||||
_, err := cache.downloader.Download(buf, &s3.GetObjectInput{
|
||||
Bucket: aws.String(cache.bucketName),
|
||||
Key: aws.String(fmt.Sprintf("%s/%s", imageBucket, imageID)), //TODO add prefix
|
||||
Key: aws.String(fmt.Sprintf("%s/%s", artifactBucket, imageID)), //TODO add prefix
|
||||
})
|
||||
if err != nil {
|
||||
return types.ImageInfo{}, xerrors.Errorf("failed to get image from the cache: %w", err)
|
||||
return types.ArtifactInfo{}, xerrors.Errorf("failed to get image from the cache: %w", err)
|
||||
}
|
||||
err = json.Unmarshal(buf.Bytes(), &info)
|
||||
if err != nil {
|
||||
return types.ImageInfo{}, xerrors.Errorf("JSON unmarshal error: %w", err)
|
||||
return types.ArtifactInfo{}, xerrors.Errorf("JSON unmarshal error: %w", err)
|
||||
}
|
||||
|
||||
return info, nil
|
||||
@@ -127,7 +128,7 @@ func (cache S3Cache) MissingLayers(imageID string, layerIDs []string) (bool, []s
|
||||
missingLayerIDs = append(missingLayerIDs, layerID)
|
||||
continue
|
||||
}
|
||||
if layerInfo.SchemaVersion != types.LayerJSONSchemaVersion {
|
||||
if layerInfo.SchemaVersion != types.BlobJSONSchemaVersion {
|
||||
missingLayerIDs = append(missingLayerIDs, layerID)
|
||||
}
|
||||
}
|
||||
@@ -137,7 +138,7 @@ func (cache S3Cache) MissingLayers(imageID string, layerIDs []string) (bool, []s
|
||||
// error means cache missed image info
|
||||
return true, missingLayerIDs, nil
|
||||
}
|
||||
if imageInfo.SchemaVersion != types.ImageJSONSchemaVersion {
|
||||
if imageInfo.SchemaVersion != types.ArtifactJSONSchemaVersion {
|
||||
missingImage = true
|
||||
}
|
||||
|
||||
|
||||
8
cache/s3_test.go
vendored
8
cache/s3_test.go
vendored
@@ -33,7 +33,7 @@ func TestS3Cache_PutLayer(t *testing.T) {
|
||||
}
|
||||
type args struct {
|
||||
diffID string
|
||||
layerInfo types.LayerInfo
|
||||
layerInfo types.BlobInfo
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
@@ -45,7 +45,7 @@ func TestS3Cache_PutLayer(t *testing.T) {
|
||||
name: "PutLayer",
|
||||
fields: fields{S3: mockSvc, BucketName: "test"},
|
||||
args: args{diffID: "sha256:24df0d4e20c0f42d3703bf1f1db2bdd77346c7956f74f423603d651e8e5ae8a7",
|
||||
layerInfo: types.LayerInfo{
|
||||
layerInfo: types.BlobInfo{
|
||||
SchemaVersion: 1,
|
||||
OS: &types.OS{
|
||||
Family: "alpine",
|
||||
@@ -78,7 +78,7 @@ func TestS3Cache_PutImage(t *testing.T) {
|
||||
}
|
||||
type args struct {
|
||||
imageID string
|
||||
imageConfig types.ImageInfo
|
||||
imageConfig types.ArtifactInfo
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
@@ -90,7 +90,7 @@ func TestS3Cache_PutImage(t *testing.T) {
|
||||
name: "Happy path",
|
||||
fields: fields{S3: mockSvc, BucketName: "test"},
|
||||
args: args{imageID: "sha256:58701fd185bda36cab0557bb6438661831267aa4a9e0b54211c4d5317a48aff4",
|
||||
imageConfig: types.ImageInfo{
|
||||
imageConfig: types.ArtifactInfo{
|
||||
SchemaVersion: 1,
|
||||
Architecture: "amd64",
|
||||
Created: time.Date(2020, 1, 2, 3, 4, 5, 0, time.UTC),
|
||||
|
||||
BIN
cache/testdata/broken-image.db
vendored
BIN
cache/testdata/broken-image.db
vendored
Binary file not shown.
BIN
cache/testdata/broken-layer.db
vendored
BIN
cache/testdata/broken-layer.db
vendored
Binary file not shown.
BIN
cache/testdata/different-image-schema.db
vendored
BIN
cache/testdata/different-image-schema.db
vendored
Binary file not shown.
BIN
cache/testdata/fanal.db
vendored
BIN
cache/testdata/fanal.db
vendored
Binary file not shown.
@@ -89,7 +89,7 @@ func run() (err error) {
|
||||
}
|
||||
|
||||
a := analyzer.NewApplier(c)
|
||||
mergedLayer, err := a.ApplyLayers(imageInfo.ID, imageInfo.LayerIDs)
|
||||
mergedLayer, err := a.ApplyLayers(imageInfo.ID, imageInfo.BlobIDs)
|
||||
if err != nil {
|
||||
switch err {
|
||||
case analyzer.ErrUnknownOS, analyzer.ErrNoPkgsDetected:
|
||||
|
||||
@@ -98,7 +98,7 @@ func containsLibrary(e godeptypes.Library, s []types.LibraryInfo) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func lookupOriginLayerForPkg(pkg types.Package, layers []types.LayerInfo) (string, string) {
|
||||
func lookupOriginLayerForPkg(pkg types.Package, layers []types.BlobInfo) (string, string) {
|
||||
for _, layer := range layers {
|
||||
for _, info := range layer.PackageInfos {
|
||||
if containsPackage(pkg, info.Packages) {
|
||||
@@ -109,7 +109,7 @@ func lookupOriginLayerForPkg(pkg types.Package, layers []types.LayerInfo) (strin
|
||||
return "", ""
|
||||
}
|
||||
|
||||
func lookupOriginLayerForLib(filePath string, lib godeptypes.Library, layers []types.LayerInfo) (string, string) {
|
||||
func lookupOriginLayerForLib(filePath string, lib godeptypes.Library, layers []types.BlobInfo) (string, string) {
|
||||
for _, layer := range layers {
|
||||
for _, layerApp := range layer.Applications {
|
||||
if filePath != layerApp.FilePath {
|
||||
@@ -123,10 +123,10 @@ func lookupOriginLayerForLib(filePath string, lib godeptypes.Library, layers []t
|
||||
return "", ""
|
||||
}
|
||||
|
||||
func ApplyLayers(layers []types.LayerInfo) types.ImageDetail {
|
||||
func ApplyLayers(layers []types.BlobInfo) types.ArtifactDetail {
|
||||
sep := "/"
|
||||
nestedMap := nested.Nested{}
|
||||
var mergedLayer types.ImageDetail
|
||||
var mergedLayer types.ArtifactDetail
|
||||
|
||||
for _, layer := range layers {
|
||||
for _, opqDir := range layer.OpaqueDirs {
|
||||
|
||||
@@ -21,13 +21,13 @@ import (
|
||||
|
||||
func TestApplyLayers(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
inputLayers []types.LayerInfo
|
||||
expectedImageDetail types.ImageDetail
|
||||
name string
|
||||
inputLayers []types.BlobInfo
|
||||
expectedArtifactDetail types.ArtifactDetail
|
||||
}{
|
||||
{
|
||||
name: "happy path",
|
||||
inputLayers: []types.LayerInfo{
|
||||
inputLayers: []types.BlobInfo{
|
||||
{
|
||||
SchemaVersion: 1,
|
||||
Digest: "sha256:932da51564135c98a49a34a193d6cd363d8fa4184d957fde16c9d8527b3f3b02",
|
||||
@@ -121,7 +121,7 @@ func TestApplyLayers(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedImageDetail: types.ImageDetail{
|
||||
expectedArtifactDetail: types.ArtifactDetail{
|
||||
OS: &types.OS{
|
||||
Family: "alpine",
|
||||
Name: "3.10",
|
||||
@@ -168,7 +168,7 @@ func TestApplyLayers(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "happy path with removed and updated lockfile",
|
||||
inputLayers: []types.LayerInfo{
|
||||
inputLayers: []types.BlobInfo{
|
||||
{
|
||||
SchemaVersion: 1,
|
||||
Digest: "sha256:932da51564135c98a49a34a193d6cd363d8fa4184d957fde16c9d8527b3f3b02",
|
||||
@@ -249,7 +249,7 @@ func TestApplyLayers(t *testing.T) {
|
||||
WhiteoutFiles: []string{"app/composer.lock"},
|
||||
},
|
||||
},
|
||||
expectedImageDetail: types.ImageDetail{
|
||||
expectedArtifactDetail: types.ArtifactDetail{
|
||||
OS: &types.OS{
|
||||
Family: "alpine",
|
||||
Name: "3.10",
|
||||
@@ -302,7 +302,7 @@ func TestApplyLayers(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "happy path with status.d",
|
||||
inputLayers: []types.LayerInfo{
|
||||
inputLayers: []types.BlobInfo{
|
||||
{
|
||||
SchemaVersion: 1,
|
||||
Digest: "sha256:24df0d4e20c0f42d3703bf1f1db2bdd77346c7956f74f423603d651e8e5ae8a7",
|
||||
@@ -357,7 +357,7 @@ func TestApplyLayers(t *testing.T) {
|
||||
OpaqueDirs: []string{"app"},
|
||||
},
|
||||
},
|
||||
expectedImageDetail: types.ImageDetail{
|
||||
expectedArtifactDetail: types.ArtifactDetail{
|
||||
OS: &types.OS{
|
||||
Family: "debian",
|
||||
Name: "8",
|
||||
@@ -388,19 +388,19 @@ func TestApplyLayers(t *testing.T) {
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
gotImageDetail := ApplyLayers(tc.inputLayers)
|
||||
sort.Slice(gotImageDetail.Packages, func(i, j int) bool {
|
||||
return gotImageDetail.Packages[i].Name < gotImageDetail.Packages[j].Name
|
||||
gotArtifactDetail := ApplyLayers(tc.inputLayers)
|
||||
sort.Slice(gotArtifactDetail.Packages, func(i, j int) bool {
|
||||
return gotArtifactDetail.Packages[i].Name < gotArtifactDetail.Packages[j].Name
|
||||
})
|
||||
sort.Slice(gotImageDetail.Applications, func(i, j int) bool {
|
||||
return gotImageDetail.Applications[i].FilePath < gotImageDetail.Applications[j].FilePath
|
||||
sort.Slice(gotArtifactDetail.Applications, func(i, j int) bool {
|
||||
return gotArtifactDetail.Applications[i].FilePath < gotArtifactDetail.Applications[j].FilePath
|
||||
})
|
||||
for _, app := range gotImageDetail.Applications {
|
||||
for _, app := range gotArtifactDetail.Applications {
|
||||
sort.Slice(app.Libraries, func(i, j int) bool {
|
||||
return app.Libraries[i].Library.Name < app.Libraries[j].Library.Name
|
||||
})
|
||||
}
|
||||
assert.Equal(t, tc.expectedImageDetail, gotImageDetail, tc.name)
|
||||
assert.Equal(t, tc.expectedArtifactDetail, gotArtifactDetail, tc.name)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -242,19 +242,19 @@ func TestFanal_Library_TarMode(t *testing.T) {
|
||||
func runChecks(t *testing.T, ctx context.Context, ac analyzer.Config, applier analyzer.Applier, tc testCase) {
|
||||
imageInfo, err := ac.Analyze(ctx)
|
||||
require.NoError(t, err, tc.name)
|
||||
imageDetail, err := applier.ApplyLayers(imageInfo.ID, imageInfo.LayerIDs)
|
||||
imageDetail, err := applier.ApplyLayers(imageInfo.ID, imageInfo.BlobIDs)
|
||||
require.NoError(t, err, tc.name)
|
||||
commonChecks(t, imageDetail, tc)
|
||||
}
|
||||
|
||||
func commonChecks(t *testing.T, detail types.ImageDetail, tc testCase) {
|
||||
func commonChecks(t *testing.T, detail types.ArtifactDetail, tc testCase) {
|
||||
assert.Equal(t, tc.expectedOS, *detail.OS, tc.name)
|
||||
checkPackages(t, detail, tc)
|
||||
checkPackageFromCommands(t, detail, tc)
|
||||
checkLibraries(detail, t, tc)
|
||||
}
|
||||
|
||||
func checkPackages(t *testing.T, detail types.ImageDetail, tc testCase) {
|
||||
func checkPackages(t *testing.T, detail types.ArtifactDetail, tc testCase) {
|
||||
r := strings.NewReplacer("/", "-", ":", "-")
|
||||
goldenFile := fmt.Sprintf("testdata/goldens/packages/%s.json.golden", r.Replace(tc.imageName))
|
||||
data, err := ioutil.ReadFile(goldenFile)
|
||||
@@ -274,7 +274,7 @@ func checkPackages(t *testing.T, detail types.ImageDetail, tc testCase) {
|
||||
}
|
||||
}
|
||||
|
||||
func checkLibraries(detail types.ImageDetail, t *testing.T, tc testCase) {
|
||||
func checkLibraries(detail types.ArtifactDetail, t *testing.T, tc testCase) {
|
||||
if tc.expectedLibraries != "" {
|
||||
data, _ := ioutil.ReadFile(tc.expectedLibraries)
|
||||
var expectedLibraries map[types.FilePath][]godeptypes.Library
|
||||
@@ -286,7 +286,7 @@ func checkLibraries(detail types.ImageDetail, t *testing.T, tc testCase) {
|
||||
}
|
||||
}
|
||||
|
||||
func checkPackageFromCommands(t *testing.T, detail types.ImageDetail, tc testCase) {
|
||||
func checkPackageFromCommands(t *testing.T, detail types.ArtifactDetail, tc testCase) {
|
||||
if tc.expectedPkgsFromCmds != "" {
|
||||
data, _ := ioutil.ReadFile(tc.expectedPkgsFromCmds)
|
||||
var expectedPkgsFromCmds []types.Package
|
||||
|
||||
@@ -177,7 +177,7 @@ func getRegistryURL(ctx context.Context, registryC testcontainers.Container, exp
|
||||
return url.Parse(urlStr)
|
||||
}
|
||||
|
||||
func analyze(ctx context.Context, imageRef string, opt types.DockerOption) (*types.ImageDetail, error) {
|
||||
func analyze(ctx context.Context, imageRef string, opt types.DockerOption) (*types.ArtifactDetail, error) {
|
||||
d, err := ioutil.TempDir("", "TestRegistry-*")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -209,7 +209,7 @@ func analyze(ctx context.Context, imageRef string, opt types.DockerOption) (*typ
|
||||
return nil, err
|
||||
}
|
||||
|
||||
imageDetail, err := applier.ApplyLayers(imageInfo.ID, imageInfo.LayerIDs)
|
||||
imageDetail, err := applier.ApplyLayers(imageInfo.ID, imageInfo.BlobIDs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package types
|
||||
|
||||
const (
|
||||
ImageJSONSchemaVersion = 1
|
||||
LayerJSONSchemaVersion = 1
|
||||
ArtifactJSONSchemaVersion = 1
|
||||
BlobJSONSchemaVersion = 1
|
||||
)
|
||||
|
||||
@@ -53,23 +53,15 @@ type Application struct {
|
||||
Libraries []LibraryInfo
|
||||
}
|
||||
|
||||
type ImageReference struct {
|
||||
Name string // image name or tar file name
|
||||
ID string
|
||||
LayerIDs []string
|
||||
// ArtifactReference represents a reference of container image, local filesystem and repository
|
||||
type ArtifactReference struct {
|
||||
Name string // image name, tar file name, directory or repository name
|
||||
ID string
|
||||
BlobIDs []string
|
||||
}
|
||||
|
||||
type ImageDetail struct {
|
||||
OS *OS `json:",omitempty"`
|
||||
Packages []Package `json:",omitempty"`
|
||||
Applications []Application `json:",omitempty"`
|
||||
|
||||
// HistoryPackages are packages extracted from RUN instructions
|
||||
HistoryPackages []Package `json:",omitempty"`
|
||||
}
|
||||
|
||||
// ImageInfo is stored in cache
|
||||
type ImageInfo struct {
|
||||
// ArtifactInfo is stored in cache
|
||||
type ArtifactInfo struct {
|
||||
SchemaVersion int
|
||||
Architecture string
|
||||
Created time.Time
|
||||
@@ -77,11 +69,11 @@ type ImageInfo struct {
|
||||
OS string
|
||||
|
||||
// HistoryPackages are packages extracted from RUN instructions
|
||||
HistoryPackages []Package
|
||||
HistoryPackages []Package `json:",omitempty"`
|
||||
}
|
||||
|
||||
// LayerInfo is stored in cache
|
||||
type LayerInfo struct {
|
||||
// BlobInfo is stored in cache
|
||||
type BlobInfo struct {
|
||||
SchemaVersion int
|
||||
Digest string `json:",omitempty"`
|
||||
DiffID string `json:",omitempty"`
|
||||
@@ -91,3 +83,13 @@ type LayerInfo struct {
|
||||
OpaqueDirs []string `json:",omitempty"`
|
||||
WhiteoutFiles []string `json:",omitempty"`
|
||||
}
|
||||
|
||||
// ArtifactDetail is generated by applying blobs
|
||||
type ArtifactDetail struct {
|
||||
OS *OS `json:",omitempty"`
|
||||
Packages []Package `json:",omitempty"`
|
||||
Applications []Application `json:",omitempty"`
|
||||
|
||||
// HistoryPackages are packages extracted from RUN instructions
|
||||
HistoryPackages []Package `json:",omitempty"`
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user