commit
2262a400ce
|
@ -17,8 +17,14 @@ var ErrKeelConfigNotFound = errors.New("keel configuration not found")
|
|||
|
||||
// getImages - get images from chart values
|
||||
func getImages(vals chartutil.Values) ([]*types.TrackedImage, error) {
|
||||
var images []*types.TrackedImage
|
||||
|
||||
keelCfg, err := getKeelConfig(vals)
|
||||
if err != nil {
|
||||
if err == ErrPolicyNotSpecified {
|
||||
// nothing to do
|
||||
return images, nil
|
||||
}
|
||||
log.WithFields(log.Fields{
|
||||
"error": err,
|
||||
}).Error("provider.helm: failed to get keel configuration for release")
|
||||
|
@ -26,8 +32,6 @@ func getImages(vals chartutil.Values) ([]*types.TrackedImage, error) {
|
|||
return nil, ErrKeelConfigNotFound
|
||||
}
|
||||
|
||||
var images []*types.TrackedImage
|
||||
|
||||
for _, imageDetails := range keelCfg.Images {
|
||||
imageRef, err := parseImage(vals, &imageDetails)
|
||||
if err != nil {
|
||||
|
@ -40,10 +44,10 @@ func getImages(vals chartutil.Values) ([]*types.TrackedImage, error) {
|
|||
}
|
||||
|
||||
trackedImage := &types.TrackedImage{
|
||||
Image: imageRef,
|
||||
PollSchedule: keelCfg.PollSchedule,
|
||||
Trigger: keelCfg.Trigger,
|
||||
SemverPreReleaseTags: make(map[string]string),
|
||||
Image: imageRef,
|
||||
PollSchedule: keelCfg.PollSchedule,
|
||||
Trigger: keelCfg.Trigger,
|
||||
Policy: keelCfg.Plc,
|
||||
}
|
||||
|
||||
images = append(images, trackedImage)
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/keel-hq/keel/internal/policy"
|
||||
"github.com/keel-hq/keel/types"
|
||||
"github.com/keel-hq/keel/util/image"
|
||||
"k8s.io/helm/pkg/chartutil"
|
||||
|
@ -47,9 +48,9 @@ func Test_getImages(t *testing.T) {
|
|||
},
|
||||
want: []*types.TrackedImage{
|
||||
&types.TrackedImage{
|
||||
Image: img,
|
||||
Trigger: types.TriggerTypePoll,
|
||||
SemverPreReleaseTags: make(map[string]string),
|
||||
Image: img,
|
||||
Trigger: types.TriggerTypePoll,
|
||||
Policy: policy.NewSemverPolicy(policy.SemverPolicyTypeAll),
|
||||
},
|
||||
},
|
||||
wantErr: false,
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package helm
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
@ -44,6 +45,11 @@ func init() {
|
|||
prometheus.MustRegister(helmUnversionedUpdatesCounter)
|
||||
}
|
||||
|
||||
// ErrPolicyNotSpecified helm related errors
|
||||
var (
|
||||
ErrPolicyNotSpecified = errors.New("policy not specified")
|
||||
)
|
||||
|
||||
// Manager - high level interface into helm provider related data used by
|
||||
// triggers
|
||||
type Manager interface {
|
||||
|
@ -426,7 +432,7 @@ func getKeelConfig(vals chartutil.Values) (*KeelChartConfig, error) {
|
|||
}
|
||||
|
||||
if r.Keel.Policy == "" {
|
||||
return nil, fmt.Errorf("policy not specified")
|
||||
return nil, ErrPolicyNotSpecified
|
||||
}
|
||||
|
||||
cfg := r.Keel
|
||||
|
|
|
@ -39,6 +39,10 @@ func checkRelease(repo *types.Repository, namespace, name string, chart *hapi_ch
|
|||
|
||||
keelCfg, err := getKeelConfig(vals)
|
||||
if err != nil {
|
||||
if err == ErrPolicyNotSpecified {
|
||||
// nothing to do
|
||||
return plan, false, nil
|
||||
}
|
||||
log.WithFields(log.Fields{
|
||||
"error": err,
|
||||
}).Error("provider.helm: failed to get keel configuration for release")
|
||||
|
|
|
@ -181,14 +181,14 @@ func (p *Provider) TrackedImages() ([]*types.TrackedImage, error) {
|
|||
}
|
||||
|
||||
trackedImages = append(trackedImages, &types.TrackedImage{
|
||||
Image: ref,
|
||||
PollSchedule: schedule,
|
||||
Trigger: trigger,
|
||||
Provider: ProviderName,
|
||||
Namespace: gr.Namespace,
|
||||
Secrets: secrets,
|
||||
Meta: make(map[string]string),
|
||||
SemverPreReleaseTags: svp,
|
||||
Image: ref,
|
||||
PollSchedule: schedule,
|
||||
Trigger: trigger,
|
||||
Provider: ProviderName,
|
||||
Namespace: gr.Namespace,
|
||||
Secrets: secrets,
|
||||
Meta: make(map[string]string),
|
||||
Policy: plc,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@ package provider
|
|||
import (
|
||||
"context"
|
||||
|
||||
"github.com/Masterminds/semver"
|
||||
"github.com/keel-hq/keel/approvals"
|
||||
"github.com/keel-hq/keel/types"
|
||||
|
||||
|
@ -116,91 +115,6 @@ func (p *DefaultProviders) TrackedImages() ([]*types.TrackedImage, error) {
|
|||
return trackedImages, nil
|
||||
}
|
||||
|
||||
func appendIfDoesntExist(tags []string, tag string) []string {
|
||||
found := false
|
||||
for _, t := range tags {
|
||||
if t == tag {
|
||||
found = true
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
return append(tags, tag)
|
||||
}
|
||||
return tags
|
||||
}
|
||||
|
||||
func appendImage(images []*types.TrackedImage, new *types.TrackedImage) []*types.TrackedImage {
|
||||
|
||||
newSemverTag, err := semver.NewVersion(new.Image.Tag())
|
||||
if err != nil {
|
||||
// not semver, just appending as a new image
|
||||
return append(images, new)
|
||||
}
|
||||
|
||||
new.Tags = appendIfDoesntExist(new.Tags, new.Image.Tag())
|
||||
|
||||
// looking for a semver image
|
||||
idx, ok := lookupSemverImageIdx(images, new)
|
||||
if !ok || len(images) == 0 {
|
||||
if newSemverTag.Prerelease() != "" {
|
||||
new.SemverPreReleaseTags[newSemverTag.Prerelease()] = new.Image.Tag()
|
||||
// new.SemverPreReleaseTags = append(new.SemverPreReleaseTags, newSemverTag.Prerelease())
|
||||
}
|
||||
return append(images, new)
|
||||
}
|
||||
|
||||
existingSemverTag, err := semver.NewVersion(images[idx].Image.Tag())
|
||||
if err != nil {
|
||||
// existing tag not semver, just appending as new image
|
||||
if newSemverTag.Prerelease() != "" {
|
||||
new.SemverPreReleaseTags[newSemverTag.Prerelease()] = new.Image.Tag()
|
||||
// new.SemverPreReleaseTags = append(new.SemverPreReleaseTags, newSemverTag.Prerelease())
|
||||
}
|
||||
return append(images, new)
|
||||
}
|
||||
|
||||
// semver, checking for prerelease tags
|
||||
if newSemverTag.Prerelease() != "" {
|
||||
_, ok := images[idx].SemverPreReleaseTags[newSemverTag.Prerelease()]
|
||||
if ok {
|
||||
// checking which is higher and setting higher
|
||||
if newSemverTag.GreaterThan(existingSemverTag) {
|
||||
images[idx].SemverPreReleaseTags[newSemverTag.Prerelease()] = new.Image.Tag()
|
||||
return images
|
||||
}
|
||||
}
|
||||
images[idx].SemverPreReleaseTags[newSemverTag.Prerelease()] = new.Image.Tag()
|
||||
}
|
||||
|
||||
// if new semver tag is a higher version, updating it as well
|
||||
if newSemverTag.GreaterThan(existingSemverTag) {
|
||||
images[idx].Image = new.Image
|
||||
}
|
||||
|
||||
images[idx].Tags = appendIfDoesntExist(images[idx].Tags, new.Image.Tag())
|
||||
|
||||
return images
|
||||
}
|
||||
|
||||
func lookupSemverImageIdx(images []*types.TrackedImage, new *types.TrackedImage) (int, bool) {
|
||||
_, err := semver.NewVersion(new.Image.Tag())
|
||||
if err != nil {
|
||||
// looking for a non semver
|
||||
return 0, false
|
||||
}
|
||||
for idx, existing := range images {
|
||||
|
||||
if existing.Image.Repository() == new.Image.Repository() {
|
||||
_, err = semver.NewVersion(existing.Image.Tag())
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
return idx, true
|
||||
}
|
||||
}
|
||||
return 0, false
|
||||
}
|
||||
|
||||
// List - list available providers
|
||||
func (p *DefaultProviders) List() []string {
|
||||
list := []string{}
|
||||
|
|
|
@ -1,254 +0,0 @@
|
|||
package provider
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/keel-hq/keel/types"
|
||||
"github.com/keel-hq/keel/util/image"
|
||||
testingUtils "github.com/keel-hq/keel/util/testing"
|
||||
)
|
||||
|
||||
func mustParse(i string) *image.Reference {
|
||||
ref, err := image.Parse(i)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return ref
|
||||
}
|
||||
|
||||
func Test_appendImage(t *testing.T) {
|
||||
type args struct {
|
||||
images []*types.TrackedImage
|
||||
new *types.TrackedImage
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want []*types.TrackedImage
|
||||
}{
|
||||
{
|
||||
name: "new image",
|
||||
args: args{
|
||||
images: []*types.TrackedImage{},
|
||||
new: testingUtils.GetTrackedImage("karolisr/webhook-demo:latest"),
|
||||
},
|
||||
want: []*types.TrackedImage{
|
||||
testingUtils.GetTrackedImage("karolisr/webhook-demo:latest"),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "new semver",
|
||||
args: args{
|
||||
images: []*types.TrackedImage{},
|
||||
new: testingUtils.GetTrackedImage("karolisr/webhook-demo:1.2.3"),
|
||||
},
|
||||
want: []*types.TrackedImage{
|
||||
testingUtils.GetTrackedImage("karolisr/webhook-demo:1.2.3"),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "new semver with prerelease",
|
||||
args: args{
|
||||
images: []*types.TrackedImage{
|
||||
testingUtils.GetTrackedImage("karolisr/webhook-demo:1.2.3"),
|
||||
},
|
||||
new: testingUtils.GetTrackedImage("karolisr/webhook-demo:1.5.0-dev"),
|
||||
},
|
||||
want: []*types.TrackedImage{
|
||||
&types.TrackedImage{
|
||||
Image: mustParse("karolisr/webhook-demo:1.5.0-dev"),
|
||||
SemverPreReleaseTags: map[string]string{
|
||||
"dev": "1.5.0-dev",
|
||||
},
|
||||
Meta: make(map[string]string),
|
||||
Tags: []string{"1.2.3", "1.5.0-dev"},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "new semver with both prereleases",
|
||||
args: args{
|
||||
images: []*types.TrackedImage{
|
||||
&types.TrackedImage{
|
||||
Image: mustParse("karolisr/webhook-demo:1.2.3-prod"),
|
||||
SemverPreReleaseTags: map[string]string{
|
||||
"prod": "1.2.3-prod",
|
||||
},
|
||||
Meta: make(map[string]string),
|
||||
Tags: []string{"1.2.3-prod"},
|
||||
},
|
||||
},
|
||||
new: testingUtils.GetTrackedImage("karolisr/webhook-demo:1.5.0-dev"),
|
||||
},
|
||||
want: []*types.TrackedImage{
|
||||
&types.TrackedImage{
|
||||
Image: mustParse("karolisr/webhook-demo:1.5.0-dev"),
|
||||
SemverPreReleaseTags: map[string]string{
|
||||
"dev": "1.5.0-dev",
|
||||
"prod": "1.2.3-prod",
|
||||
},
|
||||
Meta: make(map[string]string),
|
||||
Tags: []string{"1.2.3-prod", "1.5.0-dev"},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "semver prerelease",
|
||||
args: args{
|
||||
images: []*types.TrackedImage{},
|
||||
new: testingUtils.GetTrackedImage("karolisr/webhook-demo:1.5.0-dev"),
|
||||
},
|
||||
want: []*types.TrackedImage{
|
||||
&types.TrackedImage{
|
||||
Image: mustParse("karolisr/webhook-demo:1.5.0-dev"),
|
||||
SemverPreReleaseTags: map[string]string{
|
||||
"dev": "1.5.0-dev",
|
||||
},
|
||||
Meta: make(map[string]string),
|
||||
Tags: []string{"1.5.0-dev"},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "new semver with previous non-semver tag",
|
||||
args: args{
|
||||
images: []*types.TrackedImage{
|
||||
&types.TrackedImage{
|
||||
Image: mustParse("karolisr/webhook-demo:build-xx"),
|
||||
SemverPreReleaseTags: make(map[string]string),
|
||||
Meta: make(map[string]string),
|
||||
},
|
||||
},
|
||||
new: testingUtils.GetTrackedImage("karolisr/webhook-demo:1.5.0-dev"),
|
||||
},
|
||||
want: []*types.TrackedImage{
|
||||
&types.TrackedImage{
|
||||
Image: mustParse("karolisr/webhook-demo:build-xx"),
|
||||
SemverPreReleaseTags: make(map[string]string),
|
||||
Meta: make(map[string]string),
|
||||
},
|
||||
&types.TrackedImage{
|
||||
Image: mustParse("karolisr/webhook-demo:1.5.0-dev"),
|
||||
SemverPreReleaseTags: map[string]string{
|
||||
"dev": "1.5.0-dev",
|
||||
},
|
||||
Meta: make(map[string]string),
|
||||
Tags: []string{"1.5.0-dev"},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "mixed versions",
|
||||
args: args{
|
||||
images: []*types.TrackedImage{
|
||||
&types.TrackedImage{
|
||||
Image: mustParse("karolisr/webhook-demo:latest"),
|
||||
SemverPreReleaseTags: make(map[string]string),
|
||||
Meta: make(map[string]string),
|
||||
},
|
||||
&types.TrackedImage{
|
||||
Image: mustParse("karolisr/webhook-demo:build-foo"),
|
||||
SemverPreReleaseTags: make(map[string]string),
|
||||
Meta: make(map[string]string),
|
||||
},
|
||||
&types.TrackedImage{
|
||||
Image: mustParse("karolisr/webhook-demo:1.5.0-prod"),
|
||||
SemverPreReleaseTags: map[string]string{
|
||||
"prod": "1.5.0-prod",
|
||||
},
|
||||
Meta: make(map[string]string),
|
||||
Tags: []string{"1.5.0-prod"},
|
||||
},
|
||||
},
|
||||
new: testingUtils.GetTrackedImage("karolisr/webhook-demo:1.7.0-dev"),
|
||||
},
|
||||
want: []*types.TrackedImage{
|
||||
&types.TrackedImage{
|
||||
Image: mustParse("karolisr/webhook-demo:latest"),
|
||||
SemverPreReleaseTags: make(map[string]string),
|
||||
Meta: make(map[string]string),
|
||||
},
|
||||
&types.TrackedImage{
|
||||
Image: mustParse("karolisr/webhook-demo:build-foo"),
|
||||
SemverPreReleaseTags: make(map[string]string),
|
||||
Meta: make(map[string]string),
|
||||
},
|
||||
&types.TrackedImage{
|
||||
Image: mustParse("karolisr/webhook-demo:1.7.0-dev"),
|
||||
SemverPreReleaseTags: map[string]string{
|
||||
"prod": "1.5.0-prod",
|
||||
"dev": "1.7.0-dev",
|
||||
},
|
||||
Meta: make(map[string]string),
|
||||
Tags: []string{"1.5.0-prod", "1.7.0-dev"},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := appendImage(tt.args.images, tt.args.new); !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("appendImage() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_lookupSemverImageIdx(t *testing.T) {
|
||||
type args struct {
|
||||
images []*types.TrackedImage
|
||||
new *types.TrackedImage
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want int
|
||||
want1 bool
|
||||
}{
|
||||
{
|
||||
name: "different image",
|
||||
args: args{
|
||||
images: []*types.TrackedImage{
|
||||
testingUtils.GetTrackedImage("karolisr/webhook-demo:1.7.0-dev"),
|
||||
},
|
||||
new: testingUtils.GetTrackedImage("karolisr/foo:latest"),
|
||||
},
|
||||
want: 0,
|
||||
want1: false,
|
||||
},
|
||||
{
|
||||
name: "empty",
|
||||
args: args{
|
||||
images: []*types.TrackedImage{},
|
||||
new: testingUtils.GetTrackedImage("karolisr/foo:latest"),
|
||||
},
|
||||
want: 0,
|
||||
want1: false,
|
||||
},
|
||||
{
|
||||
name: "semver second",
|
||||
args: args{
|
||||
images: []*types.TrackedImage{
|
||||
testingUtils.GetTrackedImage("karolisr/webhook-demo:dev"),
|
||||
testingUtils.GetTrackedImage("karolisr/webhook-demo:1.7.0-dev"),
|
||||
testingUtils.GetTrackedImage("karolisr/webhook-demo:test"),
|
||||
},
|
||||
new: testingUtils.GetTrackedImage("karolisr/webhook-demo:1.5.0"),
|
||||
},
|
||||
want: 1,
|
||||
want1: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got, got1 := lookupSemverImageIdx(tt.args.images, tt.args.new)
|
||||
if got != tt.want {
|
||||
t.Errorf("lookupSemverImageIdx() got = %v, want %v", got, tt.want)
|
||||
}
|
||||
if got1 != tt.want1 {
|
||||
t.Errorf("lookupSemverImageIdx() got1 = %v, want %v", got1, tt.want1)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
|
@ -163,6 +163,63 @@ func TestPollingSemverUpdate(t *testing.T) {
|
|||
t.Errorf("update failed: %s", err)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("UpdateThroughDockerHubPollingC", func(t *testing.T) {
|
||||
|
||||
testNamespace := createNamespaceForTest()
|
||||
defer deleteTestNamespace(testNamespace)
|
||||
|
||||
dep := &apps_v1.Deployment{
|
||||
meta_v1.TypeMeta{},
|
||||
meta_v1.ObjectMeta{
|
||||
Name: "deployment-2",
|
||||
Namespace: testNamespace,
|
||||
Labels: map[string]string{
|
||||
types.KeelPolicyLabel: "major",
|
||||
types.KeelTriggerLabel: "poll",
|
||||
},
|
||||
Annotations: map[string]string{
|
||||
types.KeelPollScheduleAnnotation: "@every 2s",
|
||||
},
|
||||
},
|
||||
apps_v1.DeploymentSpec{
|
||||
Selector: &meta_v1.LabelSelector{
|
||||
MatchLabels: map[string]string{
|
||||
"app": "wd-1",
|
||||
},
|
||||
},
|
||||
Template: v1.PodTemplateSpec{
|
||||
ObjectMeta: meta_v1.ObjectMeta{
|
||||
Labels: map[string]string{
|
||||
"app": "wd-1",
|
||||
"release": "1",
|
||||
},
|
||||
},
|
||||
Spec: v1.PodSpec{
|
||||
Containers: []v1.Container{
|
||||
v1.Container{
|
||||
Name: "wd-1",
|
||||
Image: "keelhq/push-workflow-example:0.3.0-alpha",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
apps_v1.DeploymentStatus{},
|
||||
}
|
||||
|
||||
_, err := kcs.AppsV1().Deployments(testNamespace).Create(dep)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create deployment: %s", err)
|
||||
}
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*10)
|
||||
defer cancel()
|
||||
|
||||
err = waitFor(ctx, kcs, testNamespace, dep.ObjectMeta.Name, "keelhq/push-workflow-example:0.11.0-alpha")
|
||||
if err != nil {
|
||||
t.Errorf("update failed: %s", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestPollingPrivateRegistry(t *testing.T) {
|
||||
|
|
|
@ -1,12 +1,10 @@
|
|||
package poll
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/Masterminds/semver"
|
||||
"sort"
|
||||
|
||||
"github.com/keel-hq/keel/extension/credentialshelper"
|
||||
"github.com/keel-hq/keel/internal/policy"
|
||||
"github.com/keel-hq/keel/provider"
|
||||
"github.com/keel-hq/keel/registry"
|
||||
"github.com/keel-hq/keel/types"
|
||||
|
@ -23,7 +21,7 @@ type WatchRepositoryTagsJob struct {
|
|||
registryClient registry.Client
|
||||
details *watchDetails
|
||||
|
||||
latests map[string]string // a map of prerelease tags and their corresponding latest versions
|
||||
// latests map[string]string // a map of prerelease tags and their corresponding latest versions
|
||||
}
|
||||
|
||||
// NewWatchRepositoryTagsJob - new tags watcher job
|
||||
|
@ -32,7 +30,7 @@ func NewWatchRepositoryTagsJob(providers provider.Providers, registryClient regi
|
|||
providers: providers,
|
||||
registryClient: registryClient,
|
||||
details: details,
|
||||
latests: details.trackedImage.SemverPreReleaseTags,
|
||||
// latests: details.trackedImage.SemverPreReleaseTags,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -83,104 +81,116 @@ func (j *WatchRepositoryTagsJob) Run() {
|
|||
}
|
||||
}
|
||||
|
||||
func (j *WatchRepositoryTagsJob) processTags(tags []string) error {
|
||||
var errors []string
|
||||
|
||||
log.WithFields(log.Fields{
|
||||
"latest": j.details.latest,
|
||||
"all_tags": tags,
|
||||
}).Debug("trigger.poll.WatchRepositoryTagsJob: checking for new version")
|
||||
latestVersion, newAvailable, err := version.NewAvailable(j.details.latest, tags, false)
|
||||
func (j *WatchRepositoryTagsJob) computeEvents(tags []string) ([]types.Event, error) {
|
||||
trackedImages, err := j.providers.TrackedImages()
|
||||
if err != nil {
|
||||
errors = append(errors, fmt.Sprintf("new available version func returned an error: %s", err))
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if newAvailable {
|
||||
log.Debugf("new tag '%s' available, submitting event and assigning it to be the latest", latestVersion)
|
||||
// updating current latest
|
||||
j.details.latest = latestVersion
|
||||
event := types.Event{
|
||||
Repository: types.Repository{
|
||||
Name: j.details.trackedImage.Image.Repository(),
|
||||
Tag: latestVersion,
|
||||
},
|
||||
TriggerName: types.TriggerTypePoll.String(),
|
||||
events := []types.Event{}
|
||||
|
||||
// collapse removes all non-semver tags and only takes
|
||||
// the highest versions of each prerelease + the main version that doesn't have
|
||||
// any prereleases
|
||||
tags = collapse(tags)
|
||||
|
||||
for _, trackedImage := range getRelatedTrackedImages(j.details.trackedImage, trackedImages) {
|
||||
// matches, going through tags
|
||||
for _, tag := range tags {
|
||||
update, err := trackedImage.Policy.ShouldUpdate(trackedImage.Image.Tag(), tag)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
if update && !exists(tag, events) {
|
||||
event := types.Event{
|
||||
Repository: types.Repository{
|
||||
Name: j.details.trackedImage.Image.Repository(),
|
||||
Tag: tag,
|
||||
},
|
||||
TriggerName: types.TriggerTypePoll.String(),
|
||||
}
|
||||
events = append(events, event)
|
||||
}
|
||||
|
||||
}
|
||||
log.WithFields(log.Fields{
|
||||
"repository": j.details.trackedImage.Image.Repository(),
|
||||
"new_tag": latestVersion,
|
||||
}).Debug("trigger.poll.WatchRepositoryTagsJob: submiting event to providers")
|
||||
err := j.providers.Submit(event)
|
||||
|
||||
}
|
||||
|
||||
return events, nil
|
||||
}
|
||||
|
||||
func exists(tag string, events []types.Event) bool {
|
||||
for _, e := range events {
|
||||
if tag == e.Repository.Tag {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// collapse gets latest available tags for main version and pre-releases
|
||||
// example:
|
||||
// [1.0.0, 1.5.0, 1.3.0-dev, 1.4.5-dev] would become [1.5.0, 1.4.5-dev]
|
||||
func collapse(tags []string) []string {
|
||||
r := map[string]string{}
|
||||
p := policy.NewSemverPolicy(policy.SemverPolicyTypeAll)
|
||||
for _, t := range tags {
|
||||
v, err := version.GetVersion(t)
|
||||
// v, err := semver.NewVersion(tag)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
stored, ok := r[v.PreRelease]
|
||||
if !ok {
|
||||
r[v.PreRelease] = t
|
||||
continue
|
||||
}
|
||||
higher, err := p.ShouldUpdate(stored, t)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
if higher {
|
||||
r[v.PreRelease] = t
|
||||
}
|
||||
}
|
||||
|
||||
result := []string{}
|
||||
for _, tag := range r {
|
||||
result = append(result, tag)
|
||||
}
|
||||
|
||||
// always sort, for test purposes
|
||||
sort.Strings(result)
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func getRelatedTrackedImages(ours *types.TrackedImage, all []*types.TrackedImage) []*types.TrackedImage {
|
||||
b := all[:0]
|
||||
for _, x := range all {
|
||||
if x.Image.Repository() == ours.Image.Repository() {
|
||||
b = append(b, x)
|
||||
}
|
||||
}
|
||||
|
||||
return b
|
||||
}
|
||||
|
||||
func (j *WatchRepositoryTagsJob) processTags(tags []string) error {
|
||||
|
||||
events, err := j.computeEvents(tags)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, e := range events {
|
||||
err = j.providers.Submit(e)
|
||||
if err != nil {
|
||||
log.WithFields(log.Fields{
|
||||
"repository": j.details.trackedImage.Image.Repository(),
|
||||
"new_tag": latestVersion,
|
||||
"new_tag": e.Repository.Tag,
|
||||
"error": err,
|
||||
}).Error("trigger.poll.WatchRepositoryTagsJob: error while submitting an event")
|
||||
}
|
||||
}
|
||||
|
||||
log.Debugf("trigger.poll.WatchRepositoryTagsJob: processing tags %s", tags)
|
||||
for _, tag := range tags {
|
||||
sv, err := semver.NewVersion(tag)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
if sv.Prerelease() == "" {
|
||||
continue
|
||||
}
|
||||
trackedVersion, ok := j.details.trackedImage.SemverPreReleaseTags[sv.Prerelease()]
|
||||
|
||||
log.WithFields(log.Fields{
|
||||
"all": tags,
|
||||
"pre_release": sv.Prerelease(),
|
||||
"tracked": trackedVersion,
|
||||
"tracked_all": j.details.trackedImage.SemverPreReleaseTags,
|
||||
}).Debug("looking for a pre-release")
|
||||
|
||||
if ok {
|
||||
latestVersion, newAvailable, err := version.NewAvailable(trackedVersion, tags, true)
|
||||
if err != nil {
|
||||
errors = append(errors, fmt.Sprintf("new available version func for tag %s returned an error: %s", trackedVersion, err))
|
||||
continue
|
||||
}
|
||||
|
||||
if newAvailable {
|
||||
// log.Debugf("new tag with prerelease '%s' available", latestVersion)
|
||||
// updating current latest
|
||||
// j.details.latest = latestVersion
|
||||
j.details.trackedImage.SemverPreReleaseTags[sv.Prerelease()] = latestVersion
|
||||
|
||||
event := types.Event{
|
||||
Repository: types.Repository{
|
||||
Name: j.details.trackedImage.Image.Repository(),
|
||||
Tag: latestVersion,
|
||||
},
|
||||
TriggerName: types.TriggerTypePoll.String(),
|
||||
}
|
||||
log.WithFields(log.Fields{
|
||||
"repository": j.details.trackedImage.Image.Repository(),
|
||||
"new_tag": latestVersion,
|
||||
}).Debug("trigger.poll.WatchRepositoryTagsJob: submiting event to providers")
|
||||
err := j.providers.Submit(event)
|
||||
if err != nil {
|
||||
log.WithFields(log.Fields{
|
||||
"repository": j.details.trackedImage.Image.Repository(),
|
||||
"new_tag": latestVersion,
|
||||
"error": err,
|
||||
}).Error("trigger.poll.WatchRepositoryTagsJob: error while submitting an event")
|
||||
}
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
errors = append(errors, fmt.Sprintf("new available version func returned an error: %s", err))
|
||||
}
|
||||
}
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
if len(errors) > 0 {
|
||||
return fmt.Errorf("errors while processing repository tags: %s", strings.Join(errors, ","))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
package poll
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/keel-hq/keel/approvals"
|
||||
"github.com/keel-hq/keel/cache/memory"
|
||||
"github.com/keel-hq/keel/internal/policy"
|
||||
"github.com/keel-hq/keel/provider"
|
||||
"github.com/keel-hq/keel/types"
|
||||
"github.com/keel-hq/keel/util/image"
|
||||
|
@ -20,10 +23,7 @@ func TestWatchMultipleTagsWithSemver(t *testing.T) {
|
|||
Trigger: types.TriggerTypePoll,
|
||||
Provider: "fp",
|
||||
PollSchedule: types.KeelPollDefaultSchedule,
|
||||
SemverPreReleaseTags: map[string]string{
|
||||
"dev": "1.0.0-dev",
|
||||
"prod": "1.5.0-prod",
|
||||
},
|
||||
Policy: policy.NewSemverPolicy(policy.SemverPolicyTypeAll),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
@ -49,19 +49,21 @@ func TestWatchMultipleTagsWithSemver(t *testing.T) {
|
|||
}
|
||||
|
||||
if len(watcher.watched) != 1 {
|
||||
t.Errorf("expected to find watching 4 entries, found: %d", len(watcher.watched))
|
||||
}
|
||||
if det, ok := watcher.watched["gcr.io/v2-namespace/hello-world"]; ok != true {
|
||||
t.Errorf("alpha watcher not found")
|
||||
if det.latest != "1.5.0" {
|
||||
t.Errorf("expected to find a tag set for multiple tags watch job")
|
||||
}
|
||||
t.Errorf("expected to find watching 1 entries, found: %d", len(watcher.watched))
|
||||
}
|
||||
}
|
||||
|
||||
func TestWatchAllTagsJobWithSemver(t *testing.T) {
|
||||
|
||||
fp := &fakeProvider{}
|
||||
reference, _ := image.Parse("foo/bar:1.1.0")
|
||||
fp := &fakeProvider{
|
||||
images: []*types.TrackedImage{
|
||||
&types.TrackedImage{
|
||||
Image: reference,
|
||||
Policy: policy.NewSemverPolicy(policy.SemverPolicyTypeMajor),
|
||||
},
|
||||
},
|
||||
}
|
||||
mem := memory.NewMemoryCache()
|
||||
am := approvals.New(mem)
|
||||
providers := provider.New([]provider.Provider{fp}, am)
|
||||
|
@ -70,16 +72,113 @@ func TestWatchAllTagsJobWithSemver(t *testing.T) {
|
|||
tagsToReturn: []string{"1.3.0-dev", "1.5.0", "1.8.0-alpha"},
|
||||
}
|
||||
|
||||
reference, _ := image.Parse("foo/bar:1.1.0")
|
||||
|
||||
details := &watchDetails{
|
||||
trackedImage: &types.TrackedImage{
|
||||
Image: reference,
|
||||
SemverPreReleaseTags: map[string]string{
|
||||
"dev": "1.2.0-dev",
|
||||
trackedImage: fp.images[0],
|
||||
}
|
||||
|
||||
job := NewWatchRepositoryTagsJob(providers, frc, details)
|
||||
|
||||
job.Run()
|
||||
|
||||
// checking whether new job was submitted
|
||||
|
||||
if len(fp.submitted) != 1 {
|
||||
tags := []string{}
|
||||
for _, s := range fp.submitted {
|
||||
tags = append(tags, s.Repository.Tag)
|
||||
}
|
||||
t.Errorf("expected 1 events, got: %d [%s]", len(fp.submitted), strings.Join(tags, ", "))
|
||||
}
|
||||
|
||||
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.5.0" {
|
||||
t.Errorf("expected event repository tag 1.5.0, but got: %s", submitted.Repository.Tag)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestWatchAllTagsPrerelease(t *testing.T) {
|
||||
|
||||
referenceB, _ := image.Parse("foo/bar:1.2.0-dev")
|
||||
|
||||
fp := &fakeProvider{
|
||||
images: []*types.TrackedImage{
|
||||
&types.TrackedImage{
|
||||
Image: referenceB,
|
||||
Policy: policy.NewSemverPolicy(policy.SemverPolicyTypeMajor),
|
||||
},
|
||||
},
|
||||
}
|
||||
mem := memory.NewMemoryCache()
|
||||
am := approvals.New(mem)
|
||||
providers := provider.New([]provider.Provider{fp}, am)
|
||||
|
||||
frc := &fakeRegistryClient{
|
||||
tagsToReturn: []string{"1.3.0-dev", "1.5.0", "1.8.0-alpha"},
|
||||
}
|
||||
|
||||
details := &watchDetails{
|
||||
trackedImage: fp.images[0],
|
||||
}
|
||||
|
||||
job := NewWatchRepositoryTagsJob(providers, frc, details)
|
||||
|
||||
job.Run()
|
||||
|
||||
// checking whether new job was submitted
|
||||
|
||||
if len(fp.submitted) != 1 {
|
||||
tags := []string{}
|
||||
for _, s := range fp.submitted {
|
||||
tags = append(tags, s.Repository.Tag)
|
||||
}
|
||||
t.Errorf("expected 1 events, got: %d [%s]", len(fp.submitted), strings.Join(tags, ", "))
|
||||
}
|
||||
|
||||
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.3.0-dev" {
|
||||
t.Errorf("expected event repository tag 1.3.0-dev, but got: %s", submitted.Repository.Tag)
|
||||
}
|
||||
}
|
||||
|
||||
func TestWatchAllTagsMixed(t *testing.T) {
|
||||
|
||||
referenceA, _ := image.Parse("foo/bar:1.0.0")
|
||||
referenceB, _ := image.Parse("foo/bar:1.2.0-dev")
|
||||
|
||||
fp := &fakeProvider{
|
||||
images: []*types.TrackedImage{
|
||||
&types.TrackedImage{
|
||||
Image: referenceB,
|
||||
Policy: policy.NewSemverPolicy(policy.SemverPolicyTypeMajor),
|
||||
},
|
||||
&types.TrackedImage{
|
||||
Image: referenceA,
|
||||
Policy: policy.NewSemverPolicy(policy.SemverPolicyTypeMajor),
|
||||
},
|
||||
},
|
||||
}
|
||||
mem := memory.NewMemoryCache()
|
||||
am := approvals.New(mem)
|
||||
providers := provider.New([]provider.Provider{fp}, am)
|
||||
|
||||
frc := &fakeRegistryClient{
|
||||
tagsToReturn: []string{"1.3.0-dev", "1.5.0", "1.8.0-alpha"},
|
||||
}
|
||||
|
||||
details := &watchDetails{
|
||||
trackedImage: fp.images[0],
|
||||
}
|
||||
|
||||
job := NewWatchRepositoryTagsJob(providers, frc, details)
|
||||
|
||||
|
@ -88,10 +187,74 @@ func TestWatchAllTagsJobWithSemver(t *testing.T) {
|
|||
// checking whether new job was submitted
|
||||
|
||||
if len(fp.submitted) != 2 {
|
||||
t.Errorf("expected 2 events, got: %d", len(fp.submitted))
|
||||
tags := []string{}
|
||||
for _, s := range fp.submitted {
|
||||
tags = append(tags, s.Repository.Tag)
|
||||
}
|
||||
t.Errorf("expected 1 events, got: %d [%s]", len(fp.submitted), strings.Join(tags, ", "))
|
||||
}
|
||||
|
||||
submitted := fp.submitted[0]
|
||||
submitted2 := fp.submitted[1]
|
||||
|
||||
if submitted.Repository.Name != "index.docker.io/foo/bar" {
|
||||
t.Errorf("unexpected event repository name: %s", submitted.Repository.Name)
|
||||
}
|
||||
|
||||
if submitted.Repository.Tag != "1.3.0-dev" {
|
||||
t.Errorf("expected event repository tag 1.3.0-dev, but got: %s", submitted.Repository.Tag)
|
||||
}
|
||||
|
||||
if submitted2.Repository.Tag != "1.5.0" {
|
||||
t.Errorf("expected event repository tag 1.5.0, but got: %s", submitted2.Repository.Tag)
|
||||
}
|
||||
}
|
||||
|
||||
func TestWatchAllTagsMixedPolicyAll(t *testing.T) {
|
||||
|
||||
referenceA, _ := image.Parse("foo/bar:1.0.0")
|
||||
referenceB, _ := image.Parse("foo/bar:1.6.0-alpha")
|
||||
|
||||
fp := &fakeProvider{
|
||||
images: []*types.TrackedImage{
|
||||
&types.TrackedImage{
|
||||
Image: referenceB,
|
||||
Policy: policy.NewSemverPolicy(policy.SemverPolicyTypeAll),
|
||||
},
|
||||
&types.TrackedImage{
|
||||
Image: referenceA,
|
||||
Policy: policy.NewSemverPolicy(policy.SemverPolicyTypeMajor),
|
||||
},
|
||||
},
|
||||
}
|
||||
mem := memory.NewMemoryCache()
|
||||
am := approvals.New(mem)
|
||||
providers := provider.New([]provider.Provider{fp}, am)
|
||||
|
||||
frc := &fakeRegistryClient{
|
||||
tagsToReturn: []string{"1.3.0-dev", "1.5.0", "1.8.0-alpha"},
|
||||
}
|
||||
|
||||
details := &watchDetails{
|
||||
trackedImage: fp.images[0],
|
||||
}
|
||||
|
||||
job := NewWatchRepositoryTagsJob(providers, frc, details)
|
||||
|
||||
job.Run()
|
||||
|
||||
// checking whether new job was submitted
|
||||
|
||||
if len(fp.submitted) != 2 {
|
||||
tags := []string{}
|
||||
for _, s := range fp.submitted {
|
||||
tags = append(tags, s.Repository.Tag)
|
||||
}
|
||||
t.Errorf("expected 1 events, got: %d [%s]", len(fp.submitted), strings.Join(tags, ", "))
|
||||
}
|
||||
|
||||
submitted := fp.submitted[0]
|
||||
submitted2 := fp.submitted[1]
|
||||
|
||||
if submitted.Repository.Name != "index.docker.io/foo/bar" {
|
||||
t.Errorf("unexpected event repository name: %s", submitted.Repository.Name)
|
||||
|
@ -101,13 +264,51 @@ func TestWatchAllTagsJobWithSemver(t *testing.T) {
|
|||
t.Errorf("expected event repository tag 1.8.0-alpha, but got: %s", submitted.Repository.Tag)
|
||||
}
|
||||
|
||||
submitted2 := fp.submitted[1]
|
||||
|
||||
if submitted2.Repository.Name != "index.docker.io/foo/bar" {
|
||||
t.Errorf("unexpected event repository name: %s", submitted.Repository.Name)
|
||||
}
|
||||
|
||||
if submitted2.Repository.Tag != "1.3.0-dev" {
|
||||
t.Errorf("expected event repository tag 1.3.0-dev, but got: %s", submitted.Repository.Tag)
|
||||
if submitted2.Repository.Tag != "1.5.0" {
|
||||
t.Errorf("expected event repository tag 1.5.0, but got: %s", submitted2.Repository.Tag)
|
||||
}
|
||||
}
|
||||
|
||||
func Test_collapse(t *testing.T) {
|
||||
type args struct {
|
||||
tags []string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want []string
|
||||
}{
|
||||
{
|
||||
name: "single version",
|
||||
args: args{tags: []string{"1.0.0"}},
|
||||
want: []string{"1.0.0"},
|
||||
},
|
||||
{
|
||||
name: "multi",
|
||||
args: args{tags: []string{"1.0.0", "1.4.0"}},
|
||||
want: []string{"1.4.0"},
|
||||
},
|
||||
{
|
||||
name: "prerelease",
|
||||
args: args{tags: []string{"1.0.0-dev", "1.4.0-dev"}},
|
||||
want: []string{"1.4.0-dev"},
|
||||
},
|
||||
{
|
||||
name: "prerelease multi",
|
||||
args: args{tags: []string{"1.3.0-bb", "1.0.0-dev", "1.4.0-dev"}},
|
||||
want: []string{"1.3.0-bb", "1.4.0-dev"},
|
||||
},
|
||||
{
|
||||
name: "prerelease multi, mixed",
|
||||
args: args{tags: []string{"1.2.0", "1.3.0-bb", "1.0.0-dev", "1.4.0-dev"}},
|
||||
want: []string{"1.2.0", "1.3.0-bb", "1.4.0-dev"},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := collapse(tt.args.tags); !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("collapse() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ import (
|
|||
"github.com/keel-hq/keel/approvals"
|
||||
"github.com/keel-hq/keel/cache/memory"
|
||||
"github.com/keel-hq/keel/extension/credentialshelper"
|
||||
"github.com/keel-hq/keel/internal/policy"
|
||||
"github.com/keel-hq/keel/provider"
|
||||
"github.com/keel-hq/keel/registry"
|
||||
"github.com/keel-hq/keel/types"
|
||||
|
@ -20,10 +21,9 @@ func mustParse(img string, schedule string) *types.TrackedImage {
|
|||
panic(err)
|
||||
}
|
||||
return &types.TrackedImage{
|
||||
Image: ref,
|
||||
PollSchedule: schedule,
|
||||
Trigger: types.TriggerTypePoll,
|
||||
SemverPreReleaseTags: make(map[string]string),
|
||||
Image: ref,
|
||||
PollSchedule: schedule,
|
||||
Trigger: types.TriggerTypePoll,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -166,7 +166,15 @@ func TestWatchTagJobLatest(t *testing.T) {
|
|||
|
||||
func TestWatchAllTagsJob(t *testing.T) {
|
||||
|
||||
fp := &fakeProvider{}
|
||||
reference, _ := image.Parse("foo/bar:1.1.0")
|
||||
fp := &fakeProvider{
|
||||
images: []*types.TrackedImage{
|
||||
&types.TrackedImage{
|
||||
Image: reference,
|
||||
Policy: policy.NewSemverPolicy(policy.SemverPolicyTypeAll),
|
||||
},
|
||||
},
|
||||
}
|
||||
mem := memory.NewMemoryCache()
|
||||
am := approvals.New(mem)
|
||||
providers := provider.New([]provider.Provider{fp}, am)
|
||||
|
@ -175,12 +183,8 @@ func TestWatchAllTagsJob(t *testing.T) {
|
|||
tagsToReturn: []string{"1.1.2", "1.1.3", "0.9.1"},
|
||||
}
|
||||
|
||||
reference, _ := image.Parse("foo/bar:1.1.0")
|
||||
|
||||
details := &watchDetails{
|
||||
trackedImage: &types.TrackedImage{
|
||||
Image: reference,
|
||||
},
|
||||
trackedImage: fp.images[0],
|
||||
}
|
||||
|
||||
job := NewWatchRepositoryTagsJob(providers, frc, details)
|
||||
|
@ -202,7 +206,15 @@ func TestWatchAllTagsJob(t *testing.T) {
|
|||
|
||||
func TestWatchAllTagsJobCurrentLatest(t *testing.T) {
|
||||
|
||||
fp := &fakeProvider{}
|
||||
reference, _ := image.Parse("foo/bar:latest")
|
||||
fp := &fakeProvider{
|
||||
images: []*types.TrackedImage{
|
||||
&types.TrackedImage{
|
||||
Image: reference,
|
||||
Policy: policy.NewForcePolicy(true),
|
||||
},
|
||||
},
|
||||
}
|
||||
mem := memory.NewMemoryCache()
|
||||
am := approvals.New(mem)
|
||||
providers := provider.New([]provider.Provider{fp}, am)
|
||||
|
@ -211,12 +223,8 @@ func TestWatchAllTagsJobCurrentLatest(t *testing.T) {
|
|||
tagsToReturn: []string{"1.1.2", "1.1.3", "0.9.1"},
|
||||
}
|
||||
|
||||
reference, _ := image.Parse("foo/bar:latest")
|
||||
|
||||
details := &watchDetails{
|
||||
trackedImage: &types.TrackedImage{
|
||||
Image: reference,
|
||||
},
|
||||
trackedImage: fp.images[0],
|
||||
}
|
||||
|
||||
job := NewWatchRepositoryTagsJob(providers, frc, details)
|
||||
|
@ -245,6 +253,8 @@ func TestWatchMultipleTags(t *testing.T) {
|
|||
Trigger: types.TriggerTypePoll,
|
||||
Provider: "fp",
|
||||
PollSchedule: types.KeelPollDefaultSchedule,
|
||||
|
||||
Policy: policy.NewSemverPolicy(policy.SemverPolicyTypeMajor),
|
||||
},
|
||||
|
||||
&types.TrackedImage{
|
||||
|
@ -252,6 +262,7 @@ func TestWatchMultipleTags(t *testing.T) {
|
|||
Image: imgB,
|
||||
Provider: "fp",
|
||||
PollSchedule: types.KeelPollDefaultSchedule,
|
||||
Policy: policy.NewSemverPolicy(policy.SemverPolicyTypeMajor),
|
||||
},
|
||||
|
||||
&types.TrackedImage{
|
||||
|
@ -259,6 +270,7 @@ func TestWatchMultipleTags(t *testing.T) {
|
|||
Image: imgC,
|
||||
Provider: "fp",
|
||||
PollSchedule: types.KeelPollDefaultSchedule,
|
||||
Policy: policy.NewForcePolicy(true),
|
||||
},
|
||||
|
||||
&types.TrackedImage{
|
||||
|
@ -266,6 +278,7 @@ func TestWatchMultipleTags(t *testing.T) {
|
|||
Image: imgD,
|
||||
Provider: "fp",
|
||||
PollSchedule: types.KeelPollDefaultSchedule,
|
||||
Policy: policy.NewForcePolicy(true),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
|
@ -22,12 +22,15 @@ type TrackedImage struct {
|
|||
Meta map[string]string // metadata supplied by providers
|
||||
// a list of pre-release tags, ie: 1.0.0-dev, 1.5.0-prod get translated into
|
||||
// dev, prod
|
||||
// SemverPreReleaseTags []string
|
||||
SemverPreReleaseTags map[string]string
|
||||
// combined semver tags
|
||||
Tags []string
|
||||
Tags []string
|
||||
Policy Policy
|
||||
}
|
||||
|
||||
type Policy interface {
|
||||
ShouldUpdate(current, new string) (bool, error)
|
||||
}
|
||||
|
||||
func (i TrackedImage) String() string {
|
||||
return fmt.Sprintf("namespace:%s,image:%s:%s,provider:%s,trigger:%s,sched:%s,secrets:%s,semver:%v,tags:%v", i.Namespace, i.Image.Repository(), i.Image.Tag(), i.Provider, i.Trigger, i.PollSchedule, i.Secrets, i.SemverPreReleaseTags, i.Tags)
|
||||
return fmt.Sprintf("namespace:%s,image:%s:%s,provider:%s,trigger:%s,sched:%s,secrets:%s", i.Namespace, i.Image.Repository(), i.Image.Tag(), i.Provider, i.Trigger, i.PollSchedule, i.Secrets)
|
||||
}
|
||||
|
|
|
@ -88,13 +88,12 @@ func GetTrackedImage(i string) *types.TrackedImage {
|
|||
panic(err)
|
||||
}
|
||||
return &types.TrackedImage{
|
||||
Image: ref,
|
||||
PollSchedule: "",
|
||||
Trigger: types.TriggerTypeDefault,
|
||||
Provider: "",
|
||||
Namespace: "",
|
||||
Meta: make(map[string]string),
|
||||
SemverPreReleaseTags: make(map[string]string),
|
||||
Tags: []string{ref.Tag()},
|
||||
Image: ref,
|
||||
PollSchedule: "",
|
||||
Trigger: types.TriggerTypeDefault,
|
||||
Provider: "",
|
||||
Namespace: "",
|
||||
Meta: make(map[string]string),
|
||||
Tags: []string{ref.Tag()},
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue