diff --git a/pkg/condition/condition.go b/pkg/condition/condition.go index 630e74e2..8a7a5f60 100644 --- a/pkg/condition/condition.go +++ b/pkg/condition/condition.go @@ -146,3 +146,43 @@ func HasConditionReason(conditions []toolchainv1alpha1.Condition, conditionType con, found := FindConditionByType(conditions, conditionType) return found && con.Reason == reason } + +// ConditionsMatch checks whether the specified conditions match and return true if they do, ignoring the value of the +// message property. +func ConditionsMatch(first, second []toolchainv1alpha1.Condition) bool { + if len(first) != len(second) { + return false + } + for _, c := range first { + if !ContainsCondition(second, c) { + return false + } + } + return true +} + +func containsConditions(conditions []toolchainv1alpha1.Condition, contains toolchainv1alpha1.Condition, ignoreMessage bool) bool { + for _, c := range conditions { + if c.Type == contains.Type { + if ignoreMessage { + return contains.Status == c.Status && contains.Reason == c.Reason + } + return contains.Status == c.Status && contains.Reason == c.Reason && contains.Message == c.Message + } + } + return false +} + +// ContainsCondition returns true if the specified list of conditions contains the specified condition and the statuses +// of the conditions match. This function does not compare the values of the message property. +// LastTransitionTime is ignored. +func ContainsCondition(conditions []toolchainv1alpha1.Condition, contains toolchainv1alpha1.Condition) bool { + return containsConditions(conditions, contains, true) +} + +// ContainsConditionWithMessage returns true if the specified list of conditions contains the specified condition and the +// statuses and the message property of the conditions match. +// LastTransitionTime is ignored. +func ContainsConditionWithMessage(conditions []toolchainv1alpha1.Condition, contains toolchainv1alpha1.Condition) bool { + return containsConditions(conditions, contains, false) +} diff --git a/pkg/condition/condition_blackbox_test.go b/pkg/condition/condition_blackbox_test.go index e1c676b5..f6cc2ce9 100644 --- a/pkg/condition/condition_blackbox_test.go +++ b/pkg/condition/condition_blackbox_test.go @@ -543,3 +543,90 @@ func reverseStatus(status apiv1.ConditionStatus) apiv1.ConditionStatus { return apiv1.ConditionFalse } } + +func TestContainsConditionWithMessage(t *testing.T) { + conditions1 := []toolchainv1alpha1.Condition{ + { + Type: toolchainv1alpha1.UserSignupComplete, + Status: apiv1.ConditionTrue, + Reason: toolchainv1alpha1.UserSignupApprovedAutomaticallyReason, + Message: "foo", + }, + { + Type: toolchainv1alpha1.UserSignupUserDeactivatingNotificationCreated, + Status: apiv1.ConditionTrue, + Reason: toolchainv1alpha1.UserSignupUserDeactivatingReason, + Message: "bar", + }, + } + require.True(t, condition.ContainsConditionWithMessage(conditions1, + toolchainv1alpha1.Condition{ + Type: toolchainv1alpha1.UserSignupUserDeactivatingNotificationCreated, + Status: apiv1.ConditionTrue, + Reason: toolchainv1alpha1.UserSignupUserDeactivatingReason, + Message: "bar", + })) + + require.False(t, condition.ContainsConditionWithMessage(conditions1, + toolchainv1alpha1.Condition{ + Type: toolchainv1alpha1.UserSignupUserDeactivatingNotificationCreated, + Status: apiv1.ConditionTrue, + Reason: toolchainv1alpha1.UserSignupUserDeactivatingReason, + Message: "foo", + })) +} + +func TestConditionsMatch(t *testing.T) { + conditions1 := []toolchainv1alpha1.Condition{ + { + Type: toolchainv1alpha1.UserSignupComplete, + Status: apiv1.ConditionTrue, + Reason: toolchainv1alpha1.UserSignupApprovedAutomaticallyReason, + Message: "", + }, + { + Type: toolchainv1alpha1.UserSignupUserDeactivatingNotificationCreated, + Status: apiv1.ConditionTrue, + Reason: toolchainv1alpha1.UserSignupUserDeactivatingReason, + Message: "", + }, + } + conditions2 := []toolchainv1alpha1.Condition{ + { + Type: toolchainv1alpha1.UserSignupComplete, + Status: apiv1.ConditionTrue, + Reason: toolchainv1alpha1.UserSignupApprovedAutomaticallyReason, + Message: "", + }, + { + Type: toolchainv1alpha1.UserSignupUserDeactivatingNotificationCreated, + Status: apiv1.ConditionFalse, + Reason: "Foo", + Message: "", + }, + } + + // The conditions are different so no match + require.False(t, condition.ConditionsMatch(conditions1, conditions2)) + + // Update the condition so that they now match + conditions2[1].Status = apiv1.ConditionTrue + conditions2[1].Reason = toolchainv1alpha1.UserSignupUserDeactivatingReason + require.True(t, condition.ConditionsMatch(conditions1, conditions2)) + + // Add another condition, now they should not match + conditions2 = append(conditions2, toolchainv1alpha1.Condition{ + Type: toolchainv1alpha1.UserSignupUserDeactivatedNotificationCreated, + Status: apiv1.ConditionTrue, + Reason: toolchainv1alpha1.UserSignupUserDeactivatedReason, + Message: "", + }) + + require.False(t, condition.ConditionsMatch(conditions1, conditions2)) + + conditions3 := []toolchainv1alpha1.Condition{} + conditions3 = append(conditions3, conditions2[0]) + conditions3 = append(conditions3, conditions2[2]) + + require.False(t, condition.ConditionsMatch(conditions1, conditions3)) +} diff --git a/pkg/test/condition.go b/pkg/test/condition.go index 580b7dc1..e453a068 100644 --- a/pkg/test/condition.go +++ b/pkg/test/condition.go @@ -2,6 +2,7 @@ package test import ( "fmt" + "github.com/codeready-toolchain/toolchain-common/pkg/condition" "time" toolchainv1alpha1 "github.com/codeready-toolchain/api/api/v1alpha1" @@ -53,19 +54,15 @@ func AssertTimestampsAreRecent(t T, conditions []toolchainv1alpha1.Condition) { } } -// ConditionsMatch returns true if the specified list A of conditions is equal to specified -// list B of conditions ignoring the order of the elements -func ConditionsMatch(actual []toolchainv1alpha1.Condition, expected ...toolchainv1alpha1.Condition) bool { - if len(expected) != len(actual) { +// ConditionsMatch returns true if the specified list of conditions (first) is equal to the other specified +// list of conditions (second) ignoring the order of the elements, and comparing the message properties also. +// Note that the alternative ConditionsMatch function in the condition package does *NOT* compare the message properties +func ConditionsMatch(first []toolchainv1alpha1.Condition, second ...toolchainv1alpha1.Condition) bool { + if len(first) != len(second) { return false } - for _, c := range expected { - if !ContainsCondition(actual, c) { - return false - } - } - for _, c := range actual { - if !ContainsCondition(expected, c) { + for _, c := range first { + if !condition.ContainsConditionWithMessage(second, c) { return false } } @@ -75,10 +72,5 @@ func ConditionsMatch(actual []toolchainv1alpha1.Condition, expected ...toolchain // ContainsCondition returns true if the specified list of conditions contains the specified condition. // LastTransitionTime is ignored. func ContainsCondition(conditions []toolchainv1alpha1.Condition, contains toolchainv1alpha1.Condition) bool { - for _, c := range conditions { - if c.Type == contains.Type { - return contains.Status == c.Status && contains.Reason == c.Reason && contains.Message == c.Message - } - } - return false + return condition.ContainsConditionWithMessage(conditions, contains) }