diff --git a/internal/predicates/source_predicate.go b/internal/predicates/source_predicate.go index 2fc03a4ce..730abd5e2 100644 --- a/internal/predicates/source_predicate.go +++ b/internal/predicates/source_predicate.go @@ -17,14 +17,15 @@ limitations under the License. package predicates import ( + "github.com/fluxcd/pkg/runtime/conditions" "sigs.k8s.io/controller-runtime/pkg/event" "sigs.k8s.io/controller-runtime/pkg/predicate" sourcev1 "github.com/fluxcd/source-controller/api/v1" ) -// SourceRevisionChangePredicate detects revision changes to the v1beta2.Artifact -// of a v1beta2.Source object. +// SourceRevisionChangePredicate detects revision changes to the v1.Artifact of +// a v1.Source object. type SourceRevisionChangePredicate struct { predicate.Funcs } @@ -53,6 +54,20 @@ func (SourceRevisionChangePredicate) Update(e event.UpdateEvent) bool { return true } + oldConditions, ok := e.ObjectOld.(conditions.Getter) + if !ok { + return false + } + + newConditions, ok := e.ObjectNew.(conditions.Getter) + if !ok { + return false + } + + if !conditions.IsReady(oldConditions) && conditions.IsReady(newConditions) { + return true + } + return false } diff --git a/internal/predicates/source_predicate_test.go b/internal/predicates/source_predicate_test.go index 14239b3dd..0accc6693 100644 --- a/internal/predicates/source_predicate_test.go +++ b/internal/predicates/source_predicate_test.go @@ -21,10 +21,13 @@ import ( "time" "github.com/onsi/gomega" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/event" + "github.com/fluxcd/pkg/apis/meta" + sourcev1 "github.com/fluxcd/source-controller/api/v1" ) @@ -46,6 +49,54 @@ func TestSourceRevisionChangePredicate_Update(t *testing.T) { {name: "old with artifact", old: sourceA, new: emptySource, want: false}, {name: "old not a source", old: notASource, new: sourceA, want: false}, {name: "new not a source", old: sourceA, new: notASource, want: false}, + { + name: "old not ready and new ready", + old: &sourceMock{ + revision: "revision-a", + conditions: []metav1.Condition{{Type: meta.ReadyCondition, Status: metav1.ConditionFalse}}, + }, + new: &sourceMock{ + revision: "revision-a", + conditions: []metav1.Condition{{Type: meta.ReadyCondition, Status: metav1.ConditionTrue}}, + }, + want: true, + }, + { + name: "old ready and new not ready", + old: &sourceMock{ + revision: "revision-a", + conditions: []metav1.Condition{{Type: meta.ReadyCondition, Status: metav1.ConditionTrue}}, + }, + new: &sourceMock{ + revision: "revision-a", + conditions: []metav1.Condition{{Type: meta.ReadyCondition, Status: metav1.ConditionFalse}}, + }, + want: false, + }, + { + name: "old not ready and new not ready", + old: &sourceMock{ + revision: "revision-a", + conditions: []metav1.Condition{{Type: meta.ReadyCondition, Status: metav1.ConditionFalse}}, + }, + new: &sourceMock{ + revision: "revision-a", + conditions: []metav1.Condition{{Type: meta.ReadyCondition, Status: metav1.ConditionFalse}}, + }, + want: false, + }, + { + name: "old ready and new ready", + old: &sourceMock{ + revision: "revision-a", + conditions: []metav1.Condition{{Type: meta.ReadyCondition, Status: metav1.ConditionTrue}}, + }, + new: &sourceMock{ + revision: "revision-a", + conditions: []metav1.Condition{{Type: meta.ReadyCondition, Status: metav1.ConditionTrue}}, + }, + want: false, + }, {name: "old nil", old: nil, new: sourceA, want: false}, {name: "new nil", old: sourceA, new: nil, want: false}, } @@ -65,7 +116,8 @@ func TestSourceRevisionChangePredicate_Update(t *testing.T) { type sourceMock struct { unstructured.Unstructured - revision string + revision string + conditions []metav1.Condition } func (m sourceMock) GetRequeueAfter() time.Duration { @@ -80,3 +132,7 @@ func (m *sourceMock) GetArtifact() *sourcev1.Artifact { } return nil } + +func (m *sourceMock) GetConditions() []metav1.Condition { + return m.conditions +}