Respect the reconcileAt annotation
The GOTK controllers all use an annotation to trigger syncing outside of the schedule (e.g., when a webhook is indicates a new revision). This commit makes the ImageRepository controller respect the annotation, by checking it when examining an image repo object. This works a little different to the other controllers, which tend to assume that any incoming event means a sync is due. The image reflector controller uses the ChangedPredicate to filter incoming evetns, as they do, but goes further to check the annotation and otherwise, the scheduled scan time.
This commit is contained in:
parent
b2e4bfed35
commit
4e5c89ae18
|
@ -31,7 +31,9 @@ import (
|
|||
ctrl "sigs.k8s.io/controller-runtime"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
|
||||
"github.com/fluxcd/pkg/apis/meta"
|
||||
"github.com/fluxcd/pkg/recorder"
|
||||
"github.com/fluxcd/pkg/runtime/predicates"
|
||||
|
||||
imagev1alpha1 "github.com/fluxcd/image-reflector-controller/api/v1alpha1"
|
||||
)
|
||||
|
@ -169,11 +171,21 @@ func (r *ImageRepositoryReconciler) shouldScan(repo imagev1alpha1.ImageRepositor
|
|||
scanInterval = repo.Spec.ScanInterval.Duration
|
||||
}
|
||||
|
||||
// never scanned; do it now
|
||||
lastTransitionTime := imagev1alpha1.GetLastTransitionTime(repo)
|
||||
if lastTransitionTime == nil {
|
||||
return true, scanInterval
|
||||
}
|
||||
|
||||
// allow for the "reconcile at" annotation
|
||||
if syncAt, ok := repo.GetAnnotations()[meta.ReconcileAtAnnotation]; ok {
|
||||
if t, err := time.Parse(time.RFC3339Nano, syncAt); err == nil && t.Before(now) {
|
||||
return true, scanInterval
|
||||
} else if err == nil {
|
||||
return false, t.Sub(now)
|
||||
}
|
||||
}
|
||||
|
||||
// when recovering, it's possible that the resource has a last
|
||||
// scan time, but there's no records because the database has been
|
||||
// dropped and created again.
|
||||
|
@ -195,5 +207,6 @@ func (r *ImageRepositoryReconciler) shouldScan(repo imagev1alpha1.ImageRepositor
|
|||
func (r *ImageRepositoryReconciler) SetupWithManager(mgr ctrl.Manager) error {
|
||||
return ctrl.NewControllerManagedBy(mgr).
|
||||
For(&imagev1alpha1.ImageRepository{}).
|
||||
WithEventFilter(predicates.ChangePredicate{}).
|
||||
Complete(r)
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ import (
|
|||
"k8s.io/apimachinery/pkg/types"
|
||||
|
||||
imagev1alpha1 "github.com/fluxcd/image-reflector-controller/api/v1alpha1"
|
||||
"github.com/fluxcd/pkg/apis/meta"
|
||||
// +kubebuilder:scaffold:imports
|
||||
)
|
||||
|
||||
|
@ -147,6 +148,50 @@ var _ = Describe("ImageRepository controller", func() {
|
|||
})
|
||||
})
|
||||
|
||||
Context("when the ImageRepository gets a 'reconcile at' annotation", func() {
|
||||
It("scans right away", func() {
|
||||
imgRepo := loadImages("test-fetch", []string{"1.0.0"})
|
||||
|
||||
repo = imagev1alpha1.ImageRepository{
|
||||
Spec: imagev1alpha1.ImageRepositorySpec{
|
||||
Image: imgRepo,
|
||||
},
|
||||
}
|
||||
objectName := types.NamespacedName{
|
||||
Name: "random",
|
||||
Namespace: "default",
|
||||
}
|
||||
|
||||
repo.Name = objectName.Name
|
||||
repo.Namespace = objectName.Namespace
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
|
||||
r := imageRepoReconciler
|
||||
err := r.Create(ctx, &repo)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
// It'll get scanned on creation
|
||||
var repoAfter imagev1alpha1.ImageRepository
|
||||
Eventually(func() bool {
|
||||
err := r.Get(context.Background(), objectName, &repoAfter)
|
||||
return err == nil && repoAfter.Status.CanonicalImageName != ""
|
||||
}, timeout, interval).Should(BeTrue())
|
||||
|
||||
lastScan := imagev1alpha1.GetLastTransitionTime(repoAfter)
|
||||
Expect(lastScan).ToNot(BeNil())
|
||||
|
||||
repoAfter.Annotations = map[string]string{
|
||||
meta.ReconcileAtAnnotation: time.Now().Add(-time.Minute).Format(time.RFC3339Nano),
|
||||
}
|
||||
Expect(r.Update(ctx, &repoAfter)).To(Succeed())
|
||||
Eventually(func() bool {
|
||||
err := r.Get(context.Background(), objectName, &repoAfter)
|
||||
return err == nil && imagev1alpha1.GetLastTransitionTime(repoAfter).After(lastScan.Time)
|
||||
}, timeout, interval).Should(BeTrue())
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
// loadImages uploads images to the local registry, and returns the
|
||||
|
|
|
@ -83,9 +83,6 @@ var _ = BeforeSuite(func(done Done) {
|
|||
err = imagev1alpha1.AddToScheme(scheme.Scheme)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
err = imagev1alpha1.AddToScheme(scheme.Scheme)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
// +kubebuilder:scaffold:scheme
|
||||
|
||||
k8sMgr, err = ctrl.NewManager(cfg, ctrl.Options{
|
||||
|
@ -140,7 +137,7 @@ var _ = AfterSuite(func() {
|
|||
|
||||
// ---
|
||||
|
||||
// the go-containerregistry test regsitry implementation does not
|
||||
// the go-containerregistry test registry implementation does not
|
||||
// serve /myimage/tags/list. Until it does, I'm adding this handler.
|
||||
// NB:
|
||||
// - assumes repo name is a single element
|
||||
|
|
8
go.mod
8
go.mod
|
@ -7,14 +7,16 @@ replace github.com/fluxcd/image-reflector-controller/api => ./api
|
|||
require (
|
||||
github.com/Masterminds/semver/v3 v3.1.0
|
||||
github.com/fluxcd/image-reflector-controller/api v0.0.0-00010101000000-000000000000
|
||||
github.com/fluxcd/pkg/apis/meta v0.0.2
|
||||
github.com/fluxcd/pkg/recorder v0.0.5
|
||||
github.com/fluxcd/pkg/runtime v0.1.0
|
||||
github.com/go-logr/logr v0.1.0
|
||||
github.com/google/go-containerregistry v0.1.1
|
||||
github.com/onsi/ginkgo v1.12.1
|
||||
github.com/onsi/gomega v1.10.1
|
||||
go.uber.org/zap v1.10.0
|
||||
k8s.io/api v0.18.6
|
||||
k8s.io/apimachinery v0.18.6
|
||||
k8s.io/api v0.18.9
|
||||
k8s.io/apimachinery v0.18.9
|
||||
k8s.io/client-go v0.18.6
|
||||
sigs.k8s.io/controller-runtime v0.6.2
|
||||
sigs.k8s.io/controller-runtime v0.6.3
|
||||
)
|
||||
|
|
15
go.sum
15
go.sum
|
@ -196,10 +196,17 @@ github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7
|
|||
github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
|
||||
github.com/evanphx/json-patch v4.5.0+incompatible h1:ouOWdg56aJriqS0huScTkVXPC5IcNrDCXZ6OoTAWu7M=
|
||||
github.com/evanphx/json-patch v4.5.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
|
||||
github.com/evanphx/json-patch v4.9.0+incompatible h1:kLcOMZeuLAJvL2BPWLMIj5oaZQobrkAqrL+WFZwQses=
|
||||
github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
|
||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
|
||||
github.com/fluxcd/pkg v0.0.4 h1:fMA6GG3FTSBFDrlB026gQJhxj4xVuvcvwP3rhX/Yqrw=
|
||||
github.com/fluxcd/pkg/apis/meta v0.0.2 h1:kyA4Y0IzNjf1joBOnFqpWG7aNDHvtLExZcaHQM7qhRI=
|
||||
github.com/fluxcd/pkg/apis/meta v0.0.2/go.mod h1:nCNps5JJOcEQr3MNDmZqI4o0chjePSUYL6Q2ktDtotU=
|
||||
github.com/fluxcd/pkg/recorder v0.0.5 h1:D8qfupahIvh6ncCMn2yTHsrzG91S05sp4zdpsbKWeaU=
|
||||
github.com/fluxcd/pkg/recorder v0.0.5/go.mod h1:2UG6EroZ6ZbqmqoL8k/cQMe09e6A36WyH4t4UDUGyuU=
|
||||
github.com/fluxcd/pkg/runtime v0.1.0 h1:mCLj5GlQZqWtK3tvtZTmfgFOLsTUY1iqg3CmEyS1nRs=
|
||||
github.com/fluxcd/pkg/runtime v0.1.0/go.mod h1:OXkrYtDLw3GhclbzvnzfSktUyxRmC3FFhXj0tVVaIX8=
|
||||
github.com/fortytw2/leaktest v1.2.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
|
||||
github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
|
@ -415,6 +422,8 @@ github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHh
|
|||
github.com/hashicorp/go-retryablehttp v0.6.4/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY=
|
||||
github.com/hashicorp/go-retryablehttp v0.6.6 h1:HJunrbHTDDbBb/ay4kxa1n+dLmttUlnP3V9oNE4hmsM=
|
||||
github.com/hashicorp/go-retryablehttp v0.6.6/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY=
|
||||
github.com/hashicorp/go-retryablehttp v0.6.7 h1:8/CAEZt/+F7kR7GevNHulKkUjLht3CPmn7egmhieNKo=
|
||||
github.com/hashicorp/go-retryablehttp v0.6.7/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY=
|
||||
github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU=
|
||||
github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
|
||||
github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
|
||||
|
@ -1087,12 +1096,16 @@ k8s.io/api v0.17.4/go.mod h1:5qxx6vjmwUVG2nHQTKGlLts8Tbok8PzHl4vHtVFuZCA=
|
|||
k8s.io/api v0.18.4/go.mod h1:lOIQAKYgai1+vz9J7YcDZwC26Z0zQewYOGWdyIPUUQ4=
|
||||
k8s.io/api v0.18.6 h1:osqrAXbOQjkKIWDTjrqxWQ3w0GkKb1KA1XkUGHHYpeE=
|
||||
k8s.io/api v0.18.6/go.mod h1:eeyxr+cwCjMdLAmr2W3RyDI0VvTawSg/3RFFBEnmZGI=
|
||||
k8s.io/api v0.18.9 h1:7VDtivqwbvLOf8hmXSd/PDSSbpCBq49MELg84EYBYiQ=
|
||||
k8s.io/api v0.18.9/go.mod h1:9u/h6sUh6FxfErv7QqetX1EB3yBMIYOBXzdcf0Gf0rc=
|
||||
k8s.io/apiextensions-apiserver v0.18.6 h1:vDlk7cyFsDyfwn2rNAO2DbmUbvXy5yT5GE3rrqOzaMo=
|
||||
k8s.io/apiextensions-apiserver v0.18.6/go.mod h1:lv89S7fUysXjLZO7ke783xOwVTm6lKizADfvUM/SS/M=
|
||||
k8s.io/apimachinery v0.17.4/go.mod h1:gxLnyZcGNdZTCLnq3fgzyg2A5BVCHTNDFrw8AmuJ+0g=
|
||||
k8s.io/apimachinery v0.18.4/go.mod h1:OaXp26zu/5J7p0f92ASynJa1pZo06YlV9fG7BoWbCko=
|
||||
k8s.io/apimachinery v0.18.6 h1:RtFHnfGNfd1N0LeSrKCUznz5xtUP1elRGvHJbL3Ntag=
|
||||
k8s.io/apimachinery v0.18.6/go.mod h1:OaXp26zu/5J7p0f92ASynJa1pZo06YlV9fG7BoWbCko=
|
||||
k8s.io/apimachinery v0.18.9 h1:3ZABKQx3F3xPWlsGhCfUl8W+JXRRblV6Wo2A3zn0pvY=
|
||||
k8s.io/apimachinery v0.18.9/go.mod h1:PF5taHbXgTEJLU+xMypMmYTXTWPJ5LaW8bfsisxnEXk=
|
||||
k8s.io/apiserver v0.17.4/go.mod h1:5ZDQ6Xr5MNBxyi3iUZXS84QOhZl+W7Oq2us/29c0j9I=
|
||||
k8s.io/apiserver v0.18.6/go.mod h1:Zt2XvTHuaZjBz6EFYzpp+X4hTmgWGy8AthNVnTdm3Wg=
|
||||
k8s.io/client-go v0.17.4/go.mod h1:ouF6o5pz3is8qU0/qYL2RnoxOPqgfuidYLowytyLJmc=
|
||||
|
@ -1137,6 +1150,8 @@ rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
|
|||
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.7/go.mod h1:PHgbrJT7lCHcxMU+mDHEm+nx46H4zuuHZkDP6icnhu0=
|
||||
sigs.k8s.io/controller-runtime v0.6.2 h1:jkAnfdTYBpFwlmBn3pS5HFO06SfxvnTZ1p5PeEF/zAA=
|
||||
sigs.k8s.io/controller-runtime v0.6.2/go.mod h1:vhcq/rlnENJ09SIRp3EveTaZ0yqH526hjf9iJdbUJ/E=
|
||||
sigs.k8s.io/controller-runtime v0.6.3 h1:SBbr+inLPEKhvlJtrvDcwIpm+uhDvp63Bl72xYJtoOE=
|
||||
sigs.k8s.io/controller-runtime v0.6.3/go.mod h1:WlZNXcM0++oyaQt4B7C2lEE5JYRs8vJUzRP4N4JpdAY=
|
||||
sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI=
|
||||
sigs.k8s.io/structured-merge-diff v1.0.1-0.20191108220359-b1b620dd3f06 h1:zD2IemQ4LmOcAumeiyDWXKUI2SO0NYDe3H6QGvPOVgU=
|
||||
sigs.k8s.io/structured-merge-diff v1.0.1-0.20191108220359-b1b620dd3f06/go.mod h1:/ULNhyfzRopfcjskuui0cTITekDduZ7ycKN3oUT9R18=
|
||||
|
|
Loading…
Reference in New Issue