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:
Teppei Fukuda
2020-05-21 10:51:29 +03:00
committed by GitHub
parent 81526ed0d9
commit a1e818ac5e
22 changed files with 857 additions and 799 deletions

View File

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

View File

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

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

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

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

View File

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

View File

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

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

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

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,6 +1,6 @@
package types
const (
ImageJSONSchemaVersion = 1
LayerJSONSchemaVersion = 1
ArtifactJSONSchemaVersion = 1
BlobJSONSchemaVersion = 1
)

View File

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