Skip to content
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
4 changes: 4 additions & 0 deletions controllers/classifier_report_collection.go
Original file line number Diff line number Diff line change
Expand Up @@ -485,6 +485,10 @@ func processOneClassifierReport(ctx context.Context, c, clusterClient client.Cli
return
}

// AgentFailureMessage is set by sveltos-agent itself, in the managed cluster, when it cannot
// refresh cr.Spec.Match; carry it over so the management-cluster copy reflects it too.
mgmtClassifierReport.Status.AgentFailureMessage = cr.Status.AgentFailureMessage

if err := updateClassifierReportStatus(ctx, c, mgmtClassifierReport, logger); err != nil {
return
}
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ require (
github.com/onsi/ginkgo/v2 v2.32.2
github.com/onsi/gomega v1.43.0
github.com/pkg/errors v0.9.1
github.com/projectsveltos/libsveltos v1.15.1-0.20260916064556-4b7dcd8c38fd
github.com/projectsveltos/libsveltos v1.15.1-0.20260920085014-ab4903957d08
github.com/prometheus/client_golang v1.24.1
github.com/spf13/pflag v1.0.10
github.com/yuin/gopher-lua v1.1.2
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -208,8 +208,8 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/projectsveltos/libsveltos v1.15.1-0.20260916064556-4b7dcd8c38fd h1:DDcvUiTbr37R6tHMrBtMFjcRtr39VGV1Mm/dVdhyQwE=
github.com/projectsveltos/libsveltos v1.15.1-0.20260916064556-4b7dcd8c38fd/go.mod h1:YKMqwREDkoQH84WTmixxsB8tN5V0cwOnWQ5hNjrg7xM=
github.com/projectsveltos/libsveltos v1.15.1-0.20260920085014-ab4903957d08 h1:QKTx/oxpWj77Cj07A2KwlhLtkQ7P4lb4sIK74sg7Ots=
github.com/projectsveltos/libsveltos v1.15.1-0.20260920085014-ab4903957d08/go.mod h1:YKMqwREDkoQH84WTmixxsB8tN5V0cwOnWQ5hNjrg7xM=
github.com/projectsveltos/lua-utils/glua-json v0.0.0-20251212200258-2b3cdcb7c0f5 h1:khnc+994UszxZYu69J+R5FKiLA/Nk1JQj0EYAkwTWz0=
github.com/projectsveltos/lua-utils/glua-json v0.0.0-20251212200258-2b3cdcb7c0f5/go.mod h1:yVL8KQFa9tmcxgwl9nwIMtKgtmIVC1zaFRSCfOwYvPY=
github.com/projectsveltos/lua-utils/glua-runes v0.0.0-20251212200258-2b3cdcb7c0f5 h1:YbsebwRwTRhV8QacvEAdFqxcxHdeu7JTVtsBovbkgos=
Expand Down
2 changes: 1 addition & 1 deletion pkg/agent/sveltos-agent-in-mgmt-cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ spec:
valueFrom:
fieldRef:
fieldPath: metadata.namespace
image: docker.io/projectsveltos/sveltos-agent@sha256:c3636950f22bcb668b28129554309ab602a166c6fab51441ef385cf0aa8034f2
image: docker.io/projectsveltos/sveltos-agent@sha256:b96485435933ac28581c310bf0a79093e5e80c2fb614095ee68f332f25d77cb0
livenessProbe:
failureThreshold: 3
httpGet:
Expand Down
2 changes: 1 addition & 1 deletion pkg/agent/sveltos-agent-in-mgmt-cluster.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ spec:
valueFrom:
fieldRef:
fieldPath: metadata.namespace
image: docker.io/projectsveltos/sveltos-agent@sha256:c3636950f22bcb668b28129554309ab602a166c6fab51441ef385cf0aa8034f2
image: docker.io/projectsveltos/sveltos-agent@sha256:b96485435933ac28581c310bf0a79093e5e80c2fb614095ee68f332f25d77cb0
livenessProbe:
failureThreshold: 3
httpGet:
Expand Down
2 changes: 1 addition & 1 deletion pkg/agent/sveltos-agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ spec:
valueFrom:
fieldRef:
fieldPath: metadata.namespace
image: docker.io/projectsveltos/sveltos-agent@sha256:c3636950f22bcb668b28129554309ab602a166c6fab51441ef385cf0aa8034f2
image: docker.io/projectsveltos/sveltos-agent@sha256:b96485435933ac28581c310bf0a79093e5e80c2fb614095ee68f332f25d77cb0
livenessProbe:
failureThreshold: 3
httpGet:
Expand Down
2 changes: 1 addition & 1 deletion pkg/agent/sveltos-agent.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ spec:
valueFrom:
fieldRef:
fieldPath: metadata.namespace
image: docker.io/projectsveltos/sveltos-agent@sha256:c3636950f22bcb668b28129554309ab602a166c6fab51441ef385cf0aa8034f2
image: docker.io/projectsveltos/sveltos-agent@sha256:b96485435933ac28581c310bf0a79093e5e80c2fb614095ee68f332f25d77cb0
livenessProbe:
failureThreshold: 3
httpGet:
Expand Down
2 changes: 1 addition & 1 deletion pkg/agent/sveltos-applier.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ spec:
valueFrom:
fieldRef:
fieldPath: metadata.namespace
image: docker.io/projectsveltos/sveltos-applier@sha256:6bea4f06b8d1d3fa988b018045727c715fce63d3d46b143e6b392aefc062e828
image: docker.io/projectsveltos/sveltos-applier@sha256:942a429b7d7ffbb5b598a26230454b29c9a8b3cf904fef1941594c0e26b04b09
livenessProbe:
failureThreshold: 3
httpGet:
Expand Down
2 changes: 1 addition & 1 deletion pkg/agent/sveltos-applier.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ spec:
valueFrom:
fieldRef:
fieldPath: metadata.namespace
image: docker.io/projectsveltos/sveltos-applier@sha256:6bea4f06b8d1d3fa988b018045727c715fce63d3d46b143e6b392aefc062e828
image: docker.io/projectsveltos/sveltos-applier@sha256:942a429b7d7ffbb5b598a26230454b29c9a8b3cf904fef1941594c0e26b04b09
livenessProbe:
failureThreshold: 3
httpGet:
Expand Down
107 changes: 107 additions & 0 deletions test/fv/agent_failure_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
/*
Copyright 2026. Sveltos SRL. All rights reserved.

This file is part of Sveltos Enterprise. See the LICENSE file at the root
of this repository.
*/

package fv_test

import (
"context"

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"

metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"

libsveltosv1beta1 "github.com/projectsveltos/libsveltos/api/v1beta1"
)

var _ = Describe("Classifier: sveltos-agent evaluation failure is surfaced", func() {
const namePrefix = "agent-failure-"

It("AgentFailureMessage is set when sveltos-agent's evaluation fails, and cleared once fixed, "+
"without disturbing the last known-good Spec.Match", Label("FV", "PULLMODE"), func() {

classifier := &libsveltosv1beta1.Classifier{
ObjectMeta: metav1.ObjectMeta{
Name: namePrefix + randomString(),
},
Spec: libsveltosv1beta1.ClassifierSpec{
ClassifierLabels: []libsveltosv1beta1.ClassifierLabel{
{Key: key, Value: value},
},
KubernetesVersionConstraints: []libsveltosv1beta1.KubernetesVersionConstraint{
{
Version: "1.20.0",
Comparison: string(libsveltosv1beta1.ComparisonGreaterThanOrEqualTo),
},
},
DeployedResourceConstraint: &libsveltosv1beta1.DeployedResourceConstraint{
// Namespace is cluster-scoped and always has at least one instance
// (kube-system, default, ...), so this is a guaranteed match as long
// as Evaluate does not error out.
ResourceSelectors: []libsveltosv1beta1.ResourceSelector{
{
Group: "",
Version: "v1",
Kind: "Namespace",
},
},
},
},
}

Byf("Creating classifier instance %s in the management cluster", classifier.Name)
Expect(k8sClient.Create(context.TODO(), classifier)).To(Succeed())

Byf("Verifying the classifier is a match before any agent-side error is introduced")
verifyClassfierIsProvisioned(classifier)
verifyClassifierReport(classifier.Name, true)
verifyAgentFailureMessage(classifier.Name, false)

Byf("Introducing a broken Lua evaluate script, so sveltos-agent's evaluation errors out")
currentClassifier := &libsveltosv1beta1.Classifier{}
Expect(k8sClient.Get(context.TODO(), types.NamespacedName{Name: classifier.Name},
currentClassifier)).To(Succeed())
currentClassifier.Spec.DeployedResourceConstraint.ResourceSelectors[0].Evaluate = "this is not valid lua {{{"
Expect(k8sClient.Update(context.TODO(), currentClassifier)).To(Succeed())

Byf("Verifying AgentFailureMessage gets set, while Spec.Match stays at its last known-good value")
verifyAgentFailureMessage(classifier.Name, true)
verifyClassifierReport(classifier.Name, true)

Byf("Fixing the Lua evaluate script")
Expect(k8sClient.Get(context.TODO(), types.NamespacedName{Name: classifier.Name},
currentClassifier)).To(Succeed())
currentClassifier.Spec.DeployedResourceConstraint.ResourceSelectors[0].Evaluate = ""
Expect(k8sClient.Update(context.TODO(), currentClassifier)).To(Succeed())

Byf("Verifying AgentFailureMessage is cleared once evaluation succeeds again")
verifyAgentFailureMessage(classifier.Name, false)
verifyClassifierReport(classifier.Name, true)
})
})

// verifyAgentFailureMessage waits for ClassifierReport.Status.AgentFailureMessage to be set (or
// cleared, if wantSet is false), on the management cluster's copy of the report.
func verifyAgentFailureMessage(classifierName string, wantSet bool) {
clusterType := libsveltosv1beta1.ClusterTypeCapi
if kindWorkloadCluster.GetKind() == libsveltosv1beta1.SveltosClusterKind {
clusterType = libsveltosv1beta1.ClusterTypeSveltos
}
classifierReportName := libsveltosv1beta1.GetClassifierReportName(classifierName, kindWorkloadCluster.GetName(), &clusterType)
Byf("Verifying ClassifierReport %s AgentFailureMessage is set: %t", classifierReportName, wantSet)
Eventually(func() bool {
currentClassifierReport := &libsveltosv1beta1.ClassifierReport{}
err := k8sClient.Get(context.TODO(),
types.NamespacedName{Namespace: kindWorkloadCluster.GetNamespace(), Name: classifierReportName},
currentClassifierReport)
if err != nil {
return false
}
return (currentClassifierReport.Status.AgentFailureMessage != nil) == wantSet
}, timeout, pollingInterval).Should(BeTrue())
}
6 changes: 6 additions & 0 deletions test/fv/fv_suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,12 @@ var _ = SynchronizedBeforeSuite(func() []byte {

return []byte{}
}, func(data []byte) {
// SynchronizedBeforeSuite's first function above only runs on process #1; this second
// function runs on every parallel process, so it needs its own SetLogger call too,
// otherwise any other process's first client.New below warns "log.SetLogger(...) was
// never called".
ctrl.SetLogger(klog.Background())

restConfig := ctrl.GetConfigOrDie()
// To get rid of the annoying request.go log
restConfig.QPS = 100
Expand Down
2 changes: 1 addition & 1 deletion test/pullmode-sveltosapplier.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ spec:
valueFrom:
fieldRef:
fieldPath: metadata.namespace
image: docker.io/projectsveltos/sveltos-applier@sha256:6bea4f06b8d1d3fa988b018045727c715fce63d3d46b143e6b392aefc062e828
image: docker.io/projectsveltos/sveltos-applier@sha256:942a429b7d7ffbb5b598a26230454b29c9a8b3cf904fef1941594c0e26b04b09
livenessProbe:
failureThreshold: 3
httpGet:
Expand Down
Loading