Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[release-2.6] Fix the conditions history in compliancyDetails #393

Merged
merged 1 commit into from
Jan 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 14 additions & 26 deletions controllers/configurationpolicy_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,10 @@ import (
common "open-cluster-management.io/config-policy-controller/pkg/common"
)

const ControllerName string = "configuration-policy-controller"
const (
ControllerName string = "configuration-policy-controller"
complianceStatusConditionLimit int = 10
)

var log = ctrl.Log.WithName(ControllerName)

Expand Down Expand Up @@ -1018,7 +1021,7 @@ func addConditionToStatus(

// do not add condition unless it does not already appear in the status
if !checkMessageSimilarity(plc.Status.CompliancyDetails[index].Conditions, cond) {
conditions := AppendCondition(plc.Status.CompliancyDetails[index].Conditions, cond, "", false)
conditions := AppendCondition(plc.Status.CompliancyDetails[index].Conditions, cond)
plc.Status.CompliancyDetails[index].Conditions = conditions
updateNeeded = true
}
Expand Down Expand Up @@ -1569,8 +1572,7 @@ func (r *ConfigurationPolicyReconciler) getMapping(
policy.Status.CompliancyDetails[index].ComplianceState = policyv1.NonCompliant

if !checkMessageSimilarity(policy.Status.CompliancyDetails[index].Conditions, cond) {
conditions := AppendCondition(policy.Status.CompliancyDetails[index].Conditions,
cond, gvk.GroupKind().Kind, false)
conditions := AppendCondition(policy.Status.CompliancyDetails[index].Conditions, cond)
policy.Status.CompliancyDetails[index].Conditions = conditions
updateNeeded = true
}
Expand Down Expand Up @@ -2280,26 +2282,19 @@ func (r *ConfigurationPolicyReconciler) checkAndUpdateResource(

// AppendCondition check and appends conditions to the policy status
func AppendCondition(
conditions []policyv1.Condition, newCond *policyv1.Condition, resourceType string, resolved ...bool,
conditions []policyv1.Condition, newCond *policyv1.Condition,
) (conditionsRes []policyv1.Condition) {
defer recoverFlow()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this looks good! One final thought: @willkutler do you recall why this is here? It was put in 3 years ago, so definitely no worries if you're not sure! fbcef07#diff-abd7bd58ac8e6e13efca328b26418fd3abf28bb9eec7112c669bbfd161e4e950
I want to make sure we're not introducing a panic somewhere, but I also don't recall seeing the "ALERT!" message in any logs...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't unfortunately - some of the code was ported from the old policy controller so Yu might have written that. I haven't seen the ALERT message in any logs either so I think it's fine to remove

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay! Let's do this!!!


lastIndex := len(conditions)
if lastIndex > 0 {
oldCond := conditions[lastIndex-1]
if IsSimilarToLastCondition(oldCond, *newCond) {
conditions[lastIndex-1] = *newCond

return conditions
}
} else {
// first condition => trigger event
conditions = append(conditions, *newCond)
if len(conditions) != 0 && IsSimilarToLastCondition(conditions[len(conditions)-1], *newCond) {
conditions[len(conditions)-1] = *newCond

return conditions
}

conditions[lastIndex-1] = *newCond
conditions = append(conditions, *newCond)

if len(conditions) > complianceStatusConditionLimit {
conditions = conditions[1:]
}

return conditions
}
Expand Down Expand Up @@ -2459,10 +2454,3 @@ func convertPolicyStatusToString(plc *policyv1.ConfigurationPolicy) (results str

return result
}

func recoverFlow() {
if r := recover(); r != nil {
// V(-2) is the error level
log.V(-2).Info("ALERT!!!! -> recovered from ", "recover", r)
}
}
66 changes: 66 additions & 0 deletions controllers/configurationpolicy_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -675,3 +675,69 @@ func TestShouldEvaluatePolicy(t *testing.T) {
)
}
}

func TestAppendCondition(t *testing.T) {
conditions := []policyv1.Condition{}
newCond1 := &policyv1.Condition{
Type: "violation",
LastTransitionTime: metav1.Time{Time: metav1.Now().Add(5 * time.Minute)},
Reason: "K8s `must have` object already exists",
Message: "some message",
}

conditions = AppendCondition(conditions, newCond1)
if len(conditions) != 1 {
t.Fatalf("Expected a single condition to be appended but the length was %d", len(conditions))
}

lastTransition := metav1.Time{Time: metav1.Now().Add(5 * time.Minute)}
newCond2 := &policyv1.Condition{
Type: "violation",
LastTransitionTime: lastTransition,
Reason: "K8s `must have` object already exists",
Message: "some message",
}
conditions = AppendCondition(conditions, newCond2)

if len(conditions) != 1 {
t.Fatalf("Expected the single condition to be updated and not appended but the length was %d", len(conditions))
}

if conditions[0].LastTransitionTime != lastTransition {
t.Fatal("The single condition was not updated with the last transition time")
}

newCond3 := &policyv1.Condition{
Type: "violation",
LastTransitionTime: lastTransition,
Reason: "K8s creation success",
Message: "some other message",
}
conditions = AppendCondition(conditions, newCond3)

if len(conditions) != 2 {
t.Fatalf("Expected the new condition to be appended but the length was %d", len(conditions))
}

if conditions[0].Reason != newCond2.Reason || conditions[1].Reason != newCond3.Reason {
t.Fatalf("Expected the new condition to be appended the order is incorrect")
}

for i := 0; i < complianceStatusConditionLimit+2; i++ {
newCond := &policyv1.Condition{
Type: "violation",
LastTransitionTime: lastTransition,
Reason: "K8s creation success",
Message: fmt.Sprintf("some other message%d", i),
}
conditions = AppendCondition(conditions, newCond)
}

if len(conditions) != complianceStatusConditionLimit {
t.Fatalf(
"Expected the conditions array to be limited to %d but the length was %d",
complianceStatusConditionLimit,
len(conditions),
)
}
}
21 changes: 21 additions & 0 deletions test/e2e/case1_pod_handling_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ package e2e
import (
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"

"open-cluster-management.io/config-policy-controller/test/utils"
)
Expand Down Expand Up @@ -47,12 +48,32 @@ var _ = Describe("Test pod obj template handling", func() {
plc := utils.GetWithTimeout(clientManagedDynamic, gvrConfigPolicy,
case1ConfigPolicyNameEnforce, testNamespace, true, defaultTimeoutSeconds)
Expect(plc).NotTo(BeNil())

Eventually(func() interface{} {
managedPlc := utils.GetWithTimeout(clientManagedDynamic, gvrConfigPolicy,
case1ConfigPolicyNameEnforce, testNamespace, true, defaultTimeoutSeconds)

return utils.GetComplianceState(managedPlc)
}, defaultTimeoutSeconds, 1).Should(Equal("Compliant"))

By("verifying status.compliancyDetails[].conditions")
Eventually(func(g Gomega) {
managedPlc := utils.GetWithTimeout(clientManagedDynamic, gvrConfigPolicy,
case1ConfigPolicyNameEnforce, testNamespace, true, defaultTimeoutSeconds)

compliancyDetails, _, _ := unstructured.NestedSlice(managedPlc.Object, "status", "compliancyDetails")
g.Expect(compliancyDetails).To(HaveLen(1))

conditions, ok := compliancyDetails[0].(map[string]interface{})["conditions"].([]interface{})
g.Expect(ok).To(BeTrue())
g.Expect(conditions).To(HaveLen(2))
g.Expect(conditions[0].(map[string]interface{})["reason"]).To(Equal("K8s creation success"))
g.Expect(conditions[1].(map[string]interface{})["reason"]).To(
Equal("K8s `must have` object already exists"),
)
}, defaultTimeoutSeconds, 1).Should(Succeed())

By("verifying that " + case1ConfigPolicyNameInform + " is compliant")
Eventually(func() interface{} {
informPlc := utils.GetWithTimeout(clientManagedDynamic, gvrConfigPolicy,
case1ConfigPolicyNameInform, testNamespace, true, defaultTimeoutSeconds)
Expand Down
3 changes: 2 additions & 1 deletion test/utils/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -206,8 +206,9 @@ func GetComplianceState(managedPlc *unstructured.Unstructured) (result interface
func GetStatusMessage(managedPlc *unstructured.Unstructured) (result interface{}) {
if managedPlc.Object["status"] != nil {
detail := managedPlc.Object["status"].(map[string]interface{})["compliancyDetails"].([]interface{})[0]
conditions := detail.(map[string]interface{})["conditions"].([]interface{})

return detail.(map[string]interface{})["conditions"].([]interface{})[0].(map[string]interface{})["message"]
return conditions[len(conditions)-1].(map[string]interface{})["message"]
}

return nil
Expand Down