keel/trigger/poll/watcher_test.go

372 lines
9.7 KiB
Go
Raw Normal View History

2017-07-02 12:29:29 +00:00
package poll
import (
"testing"
2017-09-24 12:06:28 +00:00
"time"
2017-07-02 12:29:29 +00:00
2017-11-01 18:25:28 +00:00
"github.com/keel-hq/keel/approvals"
"github.com/keel-hq/keel/cache/memory"
2018-04-28 21:01:44 +00:00
"github.com/keel-hq/keel/extension/credentialshelper"
2017-11-01 18:25:28 +00:00
"github.com/keel-hq/keel/provider"
"github.com/keel-hq/keel/registry"
"github.com/keel-hq/keel/types"
"github.com/keel-hq/keel/util/codecs"
"github.com/keel-hq/keel/util/image"
2017-07-02 12:29:29 +00:00
)
2018-04-28 21:01:44 +00:00
func mustParse(img string) *types.TrackedImage {
ref, err := image.Parse(img)
if err != nil {
panic(err)
}
return &types.TrackedImage{
Image: ref,
}
}
2017-07-02 12:29:29 +00:00
// ======== fake registry client for testing =======
type fakeRegistryClient struct {
opts registry.Opts // opts set if anything called Digest(opts Opts)
digestToReturn string
2017-07-16 19:45:48 +00:00
tagsToReturn []string
2017-07-02 12:29:29 +00:00
}
func (c *fakeRegistryClient) Get(opts registry.Opts) (*registry.Repository, error) {
2018-04-28 21:01:44 +00:00
c.opts = opts
2017-07-16 19:45:48 +00:00
return &registry.Repository{
Name: opts.Name,
Tags: c.tagsToReturn,
}, nil
2017-07-02 12:29:29 +00:00
}
func (c *fakeRegistryClient) Digest(opts registry.Opts) (digest string, err error) {
2018-04-28 21:01:44 +00:00
c.opts = opts
2017-07-02 12:29:29 +00:00
return c.digestToReturn, nil
}
// ======== fake provider for testing =======
type fakeProvider struct {
submitted []types.Event
2017-07-20 20:45:21 +00:00
images []*types.TrackedImage
2017-07-02 12:29:29 +00:00
}
func (p *fakeProvider) Submit(event types.Event) error {
p.submitted = append(p.submitted, event)
return nil
}
func (p *fakeProvider) GetName() string {
return "fakeProvider"
}
2017-07-20 20:45:21 +00:00
func (p *fakeProvider) Stop() {
return
}
func (p *fakeProvider) TrackedImages() ([]*types.TrackedImage, error) {
return p.images, nil
}
2017-07-02 12:29:29 +00:00
func TestWatchTagJob(t *testing.T) {
fp := &fakeProvider{}
2017-09-24 12:06:28 +00:00
mem := memory.NewMemoryCache(100*time.Millisecond, 100*time.Millisecond, 10*time.Millisecond)
am := approvals.New(mem, codecs.DefaultSerializer())
providers := provider.New([]provider.Provider{fp}, am)
2017-07-02 12:29:29 +00:00
frc := &fakeRegistryClient{
digestToReturn: "sha256:0604af35299dd37ff23937d115d103532948b568a9dd8197d14c256a8ab8b0bb",
}
reference, _ := image.Parse("foo/bar:1.1")
details := &watchDetails{
2018-04-28 21:01:44 +00:00
trackedImage: &types.TrackedImage{
Image: reference,
},
digest: "sha256:123123123",
2017-07-02 12:29:29 +00:00
}
job := NewWatchTagJob(providers, frc, details)
job.Run()
// checking whether new job was submitted
submitted := fp.submitted[0]
2017-07-16 19:45:48 +00:00
if submitted.Repository.Name != "index.docker.io/foo/bar" {
2017-07-02 12:29:29 +00:00
t.Errorf("unexpected event repository name: %s", submitted.Repository.Name)
}
if submitted.Repository.Tag != "1.1" {
t.Errorf("unexpected event repository tag: %s", submitted.Repository.Tag)
}
if submitted.Repository.Digest != frc.digestToReturn {
t.Errorf("unexpected event repository digest: %s", submitted.Repository.Digest)
}
// digest should be updated
if job.details.digest != frc.digestToReturn {
t.Errorf("job details digest wasn't updated")
}
}
func TestWatchTagJobLatest(t *testing.T) {
fp := &fakeProvider{}
2017-09-24 12:06:28 +00:00
mem := memory.NewMemoryCache(100*time.Millisecond, 100*time.Millisecond, 10*time.Millisecond)
am := approvals.New(mem, codecs.DefaultSerializer())
providers := provider.New([]provider.Provider{fp}, am)
2017-07-02 12:29:29 +00:00
frc := &fakeRegistryClient{
digestToReturn: "sha256:0604af35299dd37ff23937d115d103532948b568a9dd8197d14c256a8ab8b0bb",
}
reference, _ := image.Parse("foo/bar:latest")
details := &watchDetails{
2018-04-28 21:01:44 +00:00
trackedImage: &types.TrackedImage{
Image: reference,
},
digest: "sha256:123123123",
2017-07-02 12:29:29 +00:00
}
job := NewWatchTagJob(providers, frc, details)
job.Run()
// checking whether new job was submitted
submitted := fp.submitted[0]
2017-07-16 19:45:48 +00:00
if submitted.Repository.Name != "index.docker.io/foo/bar" {
2017-07-02 12:29:29 +00:00
t.Errorf("unexpected event repository name: %s", submitted.Repository.Name)
}
if submitted.Repository.Tag != "latest" {
t.Errorf("unexpected event repository tag: %s", submitted.Repository.Tag)
}
if submitted.Repository.Digest != frc.digestToReturn {
t.Errorf("unexpected event repository digest: %s", submitted.Repository.Digest)
}
// digest should be updated
if job.details.digest != frc.digestToReturn {
t.Errorf("job details digest wasn't updated")
}
}
2017-07-16 19:45:48 +00:00
func TestWatchAllTagsJob(t *testing.T) {
fp := &fakeProvider{}
2017-09-24 12:06:28 +00:00
mem := memory.NewMemoryCache(100*time.Millisecond, 100*time.Millisecond, 10*time.Millisecond)
am := approvals.New(mem, codecs.DefaultSerializer())
providers := provider.New([]provider.Provider{fp}, am)
2017-07-16 19:45:48 +00:00
frc := &fakeRegistryClient{
tagsToReturn: []string{"1.1.2", "1.1.3", "0.9.1"},
}
reference, _ := image.Parse("foo/bar:1.1.0")
details := &watchDetails{
2018-04-28 21:01:44 +00:00
trackedImage: &types.TrackedImage{
Image: reference,
},
2017-07-16 19:45:48 +00:00
}
job := NewWatchRepositoryTagsJob(providers, frc, details)
job.Run()
// checking whether new job was submitted
submitted := fp.submitted[0]
if submitted.Repository.Name != "index.docker.io/foo/bar" {
t.Errorf("unexpected event repository name: %s", submitted.Repository.Name)
}
if submitted.Repository.Tag != "1.1.3" {
t.Errorf("expected event repository tag 1.1.3, but got: %s", submitted.Repository.Tag)
}
}
2017-07-16 19:54:39 +00:00
func TestWatchAllTagsJobCurrentLatest(t *testing.T) {
fp := &fakeProvider{}
2017-09-24 12:06:28 +00:00
mem := memory.NewMemoryCache(100*time.Millisecond, 100*time.Millisecond, 10*time.Millisecond)
am := approvals.New(mem, codecs.DefaultSerializer())
providers := provider.New([]provider.Provider{fp}, am)
2017-07-16 19:54:39 +00:00
frc := &fakeRegistryClient{
tagsToReturn: []string{"1.1.2", "1.1.3", "0.9.1"},
}
reference, _ := image.Parse("foo/bar:latest")
details := &watchDetails{
2018-04-28 21:01:44 +00:00
trackedImage: &types.TrackedImage{
Image: reference,
},
2017-07-16 19:54:39 +00:00
}
job := NewWatchRepositoryTagsJob(providers, frc, details)
job.Run()
// checking whether new job was submitted
if len(fp.submitted) != 0 {
t.Errorf("expected 0 submitted events but got something: %s", fp.submitted[0].Repository)
}
}
2018-03-25 21:53:03 +00:00
func TestWatchMultipleTags(t *testing.T) {
// fake provider listening for events
imgA, _ := image.Parse("gcr.io/v2-namespace/hello-world:1.1.1")
imgB, _ := image.Parse("gcr.io/v2-namespace/greetings-world:1.1.1")
imgC, _ := image.Parse("gcr.io/v2-namespace/greetings-world:alpha")
imgD, _ := image.Parse("gcr.io/v2-namespace/greetings-world:master")
fp := &fakeProvider{
images: []*types.TrackedImage{
&types.TrackedImage{
Image: imgA,
Trigger: types.TriggerTypePoll,
Provider: "fp",
PollSchedule: types.KeelPollDefaultSchedule,
},
&types.TrackedImage{
Trigger: types.TriggerTypePoll,
Image: imgB,
Provider: "fp",
PollSchedule: types.KeelPollDefaultSchedule,
},
&types.TrackedImage{
Trigger: types.TriggerTypePoll,
Image: imgC,
Provider: "fp",
PollSchedule: types.KeelPollDefaultSchedule,
},
&types.TrackedImage{
Trigger: types.TriggerTypePoll,
Image: imgD,
Provider: "fp",
PollSchedule: types.KeelPollDefaultSchedule,
},
},
}
mem := memory.NewMemoryCache(100*time.Millisecond, 100*time.Millisecond, 10*time.Millisecond)
am := approvals.New(mem, codecs.DefaultSerializer())
providers := provider.New([]provider.Provider{fp}, am)
// returning some sha
frc := &fakeRegistryClient{
digestToReturn: "sha256:0604af35299dd37ff23937d115d103532948b568a9dd8197d14c256a8ab8b0bb",
tagsToReturn: []string{"5.0.0"},
}
watcher := NewRepositoryWatcher(providers, frc)
2018-04-28 21:01:44 +00:00
watcher.Watch(mustParse("gcr.io/v2-namespace/hello-world:1.1.1"), "@every 10m")
watcher.Watch(mustParse("gcr.io/v2-namespace/greetings-world:1.1.1"), "@every 10m")
watcher.Watch(mustParse("gcr.io/v2-namespace/greetings-world:alpha"), "@every 10m")
watcher.Watch(mustParse("gcr.io/v2-namespace/greetings-world:master"), "@every 10m")
2018-03-25 21:53:03 +00:00
if len(watcher.watched) != 4 {
t.Errorf("expected to find watching 4 entries, found: %d", len(watcher.watched))
}
if dig, ok := watcher.watched["gcr.io/v2-namespace/greetings-world:alpha"]; ok != true {
t.Errorf("alpha watcher not found")
if dig.digest != "sha256:0604af35299dd37ff23937d115d103532948b568a9dd8197d14c256a8ab8b0bb" {
t.Errorf("digest not set for alpha")
}
}
if dig, ok := watcher.watched["gcr.io/v2-namespace/greetings-world:master"]; ok != true {
t.Errorf("alpha watcher not found")
if dig.digest != "sha256:0604af35299dd37ff23937d115d103532948b568a9dd8197d14c256a8ab8b0bb" {
t.Errorf("digest not set for alpha")
}
}
if det, ok := watcher.watched["gcr.io/v2-namespace/greetings-world"]; ok != true {
t.Errorf("alpha watcher not found")
if det.latest != "5.0.0" {
t.Errorf("expected to find a tag set for multiple tags watch job")
}
}
}
2018-04-28 21:01:44 +00:00
type fakeCredentialsHelper struct {
// set by the caller
getImageRequest *types.TrackedImage
// credentials to return
creds *types.Credentials
}
func (fch *fakeCredentialsHelper) GetCredentials(image *types.TrackedImage) (*types.Credentials, error) {
fch.getImageRequest = image
return fch.creds, nil
}
func (fch *fakeCredentialsHelper) IsEnabled() bool { return true }
func TestWatchTagJobCheckCredentials(t *testing.T) {
fakeHelper := &fakeCredentialsHelper{
creds: &types.Credentials{
Username: "user-xx",
Password: "pass-xx",
},
}
credentialshelper.RegisterCredentialsHelper("fake", fakeHelper)
defer credentialshelper.UnregisterCredentialsHelper("fake")
fp := &fakeProvider{}
mem := memory.NewMemoryCache(100*time.Millisecond, 100*time.Millisecond, 10*time.Millisecond)
am := approvals.New(mem, codecs.DefaultSerializer())
providers := provider.New([]provider.Provider{fp}, am)
frc := &fakeRegistryClient{
digestToReturn: "sha256:0604af35299dd37ff23937d115d103532948b568a9dd8197d14c256a8ab8b0bb",
}
reference, _ := image.Parse("foo/bar:1.1")
details := &watchDetails{
trackedImage: &types.TrackedImage{
Image: reference,
},
digest: "sha256:123123123",
}
job := NewWatchTagJob(providers, frc, details)
job.Run()
// checking whether new job was submitted
if frc.opts.Password != "pass-xx" {
t.Errorf("unexpected password for registry: %s", frc.opts.Password)
}
if frc.opts.Username != "user-xx" {
t.Errorf("unexpected username for registry: %s", frc.opts.Username)
}
}