Skip to content

Commit

Permalink
Test: Update the fetcher test cases
Browse files Browse the repository at this point in the history
Signed-off-by: Parthiba-Hazra <parthibahazra@gmail.com>
  • Loading branch information
Parthiba-Hazra committed Mar 5, 2024
1 parent ed9e77e commit 0bb8f69
Show file tree
Hide file tree
Showing 5 changed files with 161 additions and 44 deletions.
2 changes: 0 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -514,8 +514,6 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc=
golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps=
golang.org/x/tools v0.18.0 h1:k8NLag8AGHnn+PHbl7g43CtqZAwG60vZkLqgyZgIHgQ=
golang.org/x/tools v0.18.0/go.mod h1:GL7B4CwcLLeo59yx/9UWWuNOW1n3VZ4f5axWfML7Lcg=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
Expand Down
22 changes: 16 additions & 6 deletions pkg/image/fetcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ type LayoutOption struct {
type ImagePullChecker interface {
CheckImagePullInterval(imageID string, l logging.Logger) (bool, error)
ReadImageJSON(l logging.Logger) (*ImageJSON, error)
PruneOldImages(l logging.Logger, f *Fetcher) error
UpdateImagePullRecord(l logging.Logger, imageID string, timestamp string) error
}

func intervalPolicy(options FetchOptions) bool {
Expand Down Expand Up @@ -148,7 +150,7 @@ func (f *Fetcher) Fetch(ctx context.Context, name string, options FetchOptions)
return img, err
}

err = f.PruneOldImages()
err = f.imagePullChecker.PruneOldImages(f.logger, f)
if err != nil {
f.logger.Warnf("Failed to prune images, %s", err)
}
Expand All @@ -173,7 +175,7 @@ func (f *Fetcher) Fetch(ctx context.Context, name string, options FetchOptions)

if intervalPolicy(options) {
// Update image pull record in the JSON file
if err := f.updateImagePullRecord(name, time.Now().Format(time.RFC3339)); err != nil {
if err := f.imagePullChecker.UpdateImagePullRecord(f.logger, name, time.Now().Format(time.RFC3339)); err != nil {
return nil, err
}
}
Expand Down Expand Up @@ -305,8 +307,8 @@ func (w *colorizedWriter) Write(p []byte) (n int, err error) {
return w.writer.Write([]byte(msg))
}

func (f *Fetcher) updateImagePullRecord(imageID, timestamp string) error {
imageJSON, err := ReadImageJSON(f.logger)
func UpdateImagePullRecord(l logging.Logger, imageID string, timestamp string) error {
imageJSON, err := ReadImageJSON(l)
if err != nil {
return err
}
Expand All @@ -330,11 +332,19 @@ func (f *Fetcher) updateImagePullRecord(imageID, timestamp string) error {
}

func (c *PullChecker) CheckImagePullInterval(imageID string, l logging.Logger) (bool, error) {
return CheckImagePullInterval(imageID, c.logger)
return CheckImagePullInterval(imageID, l)
}

func (c *PullChecker) ReadImageJSON(l logging.Logger) (*ImageJSON, error) {
return ReadImageJSON(c.logger)
return ReadImageJSON(l)
}

func (c *PullChecker) PruneOldImages(l logging.Logger, f *Fetcher) error {
return PruneOldImages(l, f)
}

func (c *PullChecker) UpdateImagePullRecord(l logging.Logger, imageID string, timestamp string) error {
return UpdateImagePullRecord(l, imageID, timestamp)
}

func CheckImagePullInterval(imageID string, l logging.Logger) (bool, error) {
Expand Down
163 changes: 129 additions & 34 deletions pkg/image/fetcher_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"path/filepath"
"runtime"
"testing"
"time"

"github.com/buildpacks/imgutil"

Expand All @@ -34,6 +35,8 @@ type MockPullChecker struct {
*image.PullChecker
MockCheckImagePullInterval func(imageID string, l logging.Logger) (bool, error)
MockReadImageJSON func(l logging.Logger) (*image.ImageJSON, error)
MockPruneOldImages func(l logging.Logger, f *image.Fetcher) error
MockUpdateImagePullRecord func(l logging.Logger, imageID string, timestamp string) error
}

func NewMockImagePullChecker(logger logging.Logger) *MockPullChecker {
Expand All @@ -53,13 +56,38 @@ func (m *MockPullChecker) ReadImageJSON(l logging.Logger) (*image.ImageJSON, err
if m.MockReadImageJSON != nil {
return m.MockReadImageJSON(l)
}
return &image.ImageJSON{

imageJSON = &image.ImageJSON{
Interval: &image.Interval{
PullingInterval: "7d",
PruningInterval: "7d",
LastPrune: "2023-01-01T00:00:00Z",
},
Image: &image.ImageData{
ImageIDtoTIME: map[string]string{
"repoName": "2023-01-01T00:00:00Z",
},
},
}, nil
}

return imageJSON, nil
}

func (m *MockPullChecker) PruneOldImages(l logging.Logger, f *image.Fetcher) error {
if m.MockPruneOldImages != nil {
return m.MockPruneOldImages(l, f)
}

return nil
}

func (m *MockPullChecker) UpdateImagePullRecord(l logging.Logger, imageID string, timestamp string) error {
if m.MockUpdateImagePullRecord != nil {
fmt.Printf("checking wheather its calling or not")
return m.MockUpdateImagePullRecord(l, imageID, timestamp)
}

return nil
}

func TestFetcher(t *testing.T) {
Expand Down Expand Up @@ -437,15 +465,24 @@ func testFetcher(t *testing.T, when spec.G, it spec.S) {
mockImagePullChecker.MockCheckImagePullInterval = func(imageID string, l logging.Logger) (bool, error) {
return false, nil
}

imageJSON = &image.ImageJSON{
Interval: &image.Interval{
PullingInterval: "7d",
PruningInterval: "7d",
LastPrune: "2023-01-01T00:00:00Z",
},
Image: &image.ImageData{
ImageIDtoTIME: map[string]string{
repoName: "2023-01-01T00:00:00Z",
},
},
}

imageFetcher = image.NewFetcher(logging.NewLogWithWriters(&outBuf, &outBuf), docker, mockImagePullChecker)

mockImagePullChecker.MockReadImageJSON = func(l logging.Logger) (*image.ImageJSON, error) {
return &image.ImageJSON{
Image: &image.ImageData{
ImageIDtoTIME: map[string]string{
repoName: "2023-01-01T00:00:00Z",
},
},
}, nil
return imageJSON, nil
}
})

Expand All @@ -459,7 +496,8 @@ func testFetcher(t *testing.T, when spec.G, it spec.S) {
h.AssertError(t, err, fmt.Sprintf("image '%s' does not exist on the daemon", repoName))
imageJSON, err = mockImagePullChecker.ReadImageJSON(logger)
h.AssertNil(t, err)
h.AssertNil(t, imageJSON.Image.ImageIDtoTIME)
_, exists := imageJSON.Image.ImageIDtoTIME[repoName]
h.AssertEq(t, exists, false)
})
})

Expand All @@ -472,30 +510,62 @@ func testFetcher(t *testing.T, when spec.G, it spec.S) {
mockImagePullChecker.MockCheckImagePullInterval = func(imageID string, l logging.Logger) (bool, error) {
return true, nil
}

imageJSON = &image.ImageJSON{
Interval: &image.Interval{
PullingInterval: "7d",
PruningInterval: "7d",
LastPrune: "2023-01-01T00:00:00Z",
},
Image: &image.ImageData{
ImageIDtoTIME: map[string]string{
repoName: "2023-01-01T00:00:00Z",
},
},
}

mockImagePullChecker.MockReadImageJSON = func(l logging.Logger) (*image.ImageJSON, error) {
return imageJSON, nil
}

mockImagePullChecker.MockUpdateImagePullRecord = func(l logging.Logger, imageID string, timestamp string) error {
imageJSON, _ = mockImagePullChecker.ReadImageJSON(l)
imageJSON.Image.ImageIDtoTIME[repoName] = timestamp
return nil
}

imageFetcher = image.NewFetcher(logging.NewLogWithWriters(&outBuf, &outBuf), docker, mockImagePullChecker)
})

it.After(func() {
mockImagePullChecker.MockCheckImagePullInterval = nil
mockImagePullChecker.MockReadImageJSON = nil
mockImagePullChecker.MockUpdateImagePullRecord = nil
h.DockerRmi(docker, repoName)
})

it("pulls the remote image and returns it", func() {
fetchedImg, err := imageFetcher.Fetch(context.TODO(), repoName, image.FetchOptions{Daemon: true, PullPolicy: image.PullIfNotPresent})
beforeFetch, _ := time.Parse(time.RFC3339, imageJSON.Image.ImageIDtoTIME[repoName])
fmt.Printf("before fetch: %v\n", imageJSON.Image.ImageIDtoTIME[repoName])
_, err := imageFetcher.Fetch(context.TODO(), repoName, image.FetchOptions{Daemon: true, PullPolicy: image.PullWeekly})
h.AssertNil(t, err)

fetchedImgLabel, err := fetchedImg.Label(label)
h.AssertNil(t, err)
h.AssertEq(t, fetchedImgLabel, remoteImgLabel)
imageJSON, _ = mockImagePullChecker.ReadImageJSON(logger)

afterFetch, _ := time.Parse(time.RFC3339, imageJSON.Image.ImageIDtoTIME[repoName])
fmt.Printf("after fetch: %v\n", imageJSON.Image.ImageIDtoTIME[repoName])
diff := beforeFetch.Before(afterFetch)
h.AssertEq(t, diff, true)
})
})

when("there is a local image and CheckImagePullInterval returns false", func() {
it.Before(func() {
img, err := local.NewImage(repoName, docker)
localImg, err := local.NewImage(repoName, docker)
h.AssertNil(t, err)
h.AssertNil(t, localImg.SetLabel(label, "2"))

h.AssertNil(t, img.Save())
h.AssertNil(t, localImg.Save())
mockImagePullChecker.MockCheckImagePullInterval = func(imageID string, l logging.Logger) (bool, error) {
return true, nil
}
Expand All @@ -508,13 +578,19 @@ func testFetcher(t *testing.T, when spec.G, it spec.S) {
})

it("returns the local image", func() {
_, err := imageFetcher.Fetch(context.TODO(), repoName, image.FetchOptions{Daemon: true, PullPolicy: image.PullIfNotPresent})
fetchedImg, err := imageFetcher.Fetch(context.TODO(), repoName, image.FetchOptions{Daemon: true, PullPolicy: image.PullIfNotPresent})
h.AssertNil(t, err)

fetchedImgLabel, err := fetchedImg.Label(label)
h.AssertNil(t, err)
h.AssertEq(t, fetchedImgLabel, "2")
})
})
})

when("there is no a remote image", func() {
when("there is no remote image", func() {
var label string

when("there is no local image and CheckImagePullInterval returns true", func() {
it.Before(func() {
mockImagePullChecker.MockCheckImagePullInterval = func(imageID string, l logging.Logger) (bool, error) {
Expand All @@ -538,15 +614,23 @@ func testFetcher(t *testing.T, when spec.G, it spec.S) {
mockImagePullChecker.MockCheckImagePullInterval = func(imageID string, l logging.Logger) (bool, error) {
return false, nil
}

imageJSON = &image.ImageJSON{
Interval: &image.Interval{
PullingInterval: "7d",
PruningInterval: "7d",
LastPrune: "2023-01-01T00:00:00Z",
},
Image: &image.ImageData{
ImageIDtoTIME: map[string]string{
repoName: "2023-01-01T00:00:00Z",
},
},
}

imageFetcher = image.NewFetcher(logging.NewLogWithWriters(&outBuf, &outBuf), docker, mockImagePullChecker)
mockImagePullChecker.MockReadImageJSON = func(l logging.Logger) (*image.ImageJSON, error) {
return &image.ImageJSON{
Image: &image.ImageData{
ImageIDtoTIME: map[string]string{
repoName: "2023-01-01T00:00:00Z",
},
},
}, nil
return imageJSON, nil
}
})

Expand All @@ -560,16 +644,18 @@ func testFetcher(t *testing.T, when spec.G, it spec.S) {
h.AssertError(t, err, fmt.Sprintf("image '%s' does not exist on the daemon", repoName))
imageJSON, err = mockImagePullChecker.ReadImageJSON(logger)
h.AssertNil(t, err)
h.AssertNil(t, imageJSON.Image.ImageIDtoTIME)
_, exists := imageJSON.Image.ImageIDtoTIME[repoName]
h.AssertEq(t, exists, false)
})
})

when("there is a local image and CheckImagePullInterval returns true", func() {
it.Before(func() {
img, err := local.NewImage(repoName, docker)
localImg, err := local.NewImage(repoName, docker)
h.AssertNil(t, err)
h.AssertNil(t, localImg.SetLabel(label, "2"))

h.AssertNil(t, img.Save())
h.AssertNil(t, localImg.Save())
mockImagePullChecker.MockCheckImagePullInterval = func(imageID string, l logging.Logger) (bool, error) {
return true, nil
}
Expand All @@ -581,18 +667,23 @@ func testFetcher(t *testing.T, when spec.G, it spec.S) {
h.DockerRmi(docker, repoName)
})

it("try to pull the remote image and returns error", func() {
_, err := imageFetcher.Fetch(context.TODO(), repoName, image.FetchOptions{Daemon: true, PullPolicy: image.PullIfNotPresent})
h.AssertNotNil(t, err)
it("try to pull the remote image and returns local image", func() {
fetchedImg, err := imageFetcher.Fetch(context.TODO(), repoName, image.FetchOptions{Daemon: true, PullPolicy: image.PullIfNotPresent})
h.AssertNil(t, err)

fetchedImgLabel, err := fetchedImg.Label(label)
h.AssertNil(t, err)
h.AssertEq(t, fetchedImgLabel, "2")
})
})

when("there is a local image and CheckImagePullInterval returns false", func() {
it.Before(func() {
img, err := local.NewImage(repoName, docker)
localImg, err := local.NewImage(repoName, docker)
h.AssertNil(t, err)
h.AssertNil(t, localImg.SetLabel(label, "2"))

h.AssertNil(t, img.Save())
h.AssertNil(t, localImg.Save())
mockImagePullChecker.MockCheckImagePullInterval = func(imageID string, l logging.Logger) (bool, error) {
return true, nil
}
Expand All @@ -605,8 +696,12 @@ func testFetcher(t *testing.T, when spec.G, it spec.S) {
})

it("returns the local image", func() {
_, err := imageFetcher.Fetch(context.TODO(), repoName, image.FetchOptions{Daemon: true, PullPolicy: image.PullIfNotPresent})
fetchedImg, err := imageFetcher.Fetch(context.TODO(), repoName, image.FetchOptions{Daemon: true, PullPolicy: image.PullIfNotPresent})
h.AssertNil(t, err)

fetchedImgLabel, err := fetchedImg.Label(label)
h.AssertNil(t, err)
h.AssertEq(t, fetchedImgLabel, "2")
})
})
})
Expand Down
4 changes: 2 additions & 2 deletions pkg/image/pull_policy.go
Original file line number Diff line number Diff line change
Expand Up @@ -214,8 +214,8 @@ func parseDurationString(durationStr string) (time.Duration, error) {
return time.Duration(totalMinutes) * time.Minute, nil
}

func (f *Fetcher) PruneOldImages() error {
imageJSON, err := ReadImageJSON(f.logger)
func PruneOldImages(l logging.Logger, f *Fetcher) error {
imageJSON, err := ReadImageJSON(l)
if err != nil {
return err
}
Expand Down
Loading

0 comments on commit 0bb8f69

Please sign in to comment.