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
37 changes: 37 additions & 0 deletions api/v1beta1/clustersummary_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,43 @@ type HelmChartSummary struct {
// +optional
// FailureMessage provides the specific error from the Helm engine for this release
FailureMessage *string `json:"failureMessage,omitempty"`

// ChartName, RepositoryName, RepoURL, and ChartVersion mirror the fully resolved
// (post-template) HelmChart entry that produced this release, captured at deploy time.
// Never set for Flux-source-backed charts (Flux owns version resolution there).
// +optional
ChartName string `json:"chartName,omitempty"`

// +optional
RepositoryName string `json:"repositoryName,omitempty"`

// +optional
RepoURL string `json:"repoURL,omitempty"`

// +optional
ChartVersion string `json:"chartVersion,omitempty"`

// CredentialsSecretRef is the resolved secret reference (if any) used to authenticate
// against RepoURL, captured at deploy time. Only the reference is stored, never secret
// contents.
// +optional
CredentialsSecretRef *corev1.SecretReference `json:"credentialsSecretRef,omitempty"`

// LatestVersion is the highest version currently published upstream for this chart, if
// greater than ChartVersion. Populated by a periodic background check, independent of
// the reconcile loop. Detection only: Sveltos never mutates ChartVersion based on this.
// +optional
LatestVersion *string `json:"latestVersion,omitempty"`

// LatestPatchVersion is the highest published version sharing ChartVersion's
// major.minor, if greater than ChartVersion. Distinguishes "a same-minor patch bump is
// available" from "a newer minor/major line exists" (LatestVersion).
// +optional
LatestPatchVersion *string `json:"latestPatchVersion,omitempty"`

// LastCheckedTime is when LatestVersion/LatestPatchVersion were last evaluated.
// +optional
LastCheckedTime *metav1.Time `json:"lastCheckedTime,omitempty"`
}

// ClusterSummarySpec defines the desired state of ClusterSummary
Expand Down
24 changes: 22 additions & 2 deletions api/v1beta1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

68 changes: 41 additions & 27 deletions cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,33 +75,34 @@ import (
)

var (
setupLog = ctrl.Log.WithName("setup")
diagnosticsAddress string
insecureDiagnostics bool
shardKey string
workers int
concurrentReconciles int
agentInMgmtCluster bool
reportMode controllers.ReportMode
tmpReportMode int
restConfigQPS float32
restConfigBurst int
webhookPort int
syncPeriod time.Duration
conflictRetryTime time.Duration
healthErrorRetryTime time.Duration
version string
healthAddr string
profilerAddress string
driftDetectionConfigMap string
luaConfigMap string
capiOnboardAnnotation string
disableCaching bool
disableTelemetry bool
autoDeployDependencies bool
registry string
luaCallStackSize int
luaRegistrySize int
setupLog = ctrl.Log.WithName("setup")
diagnosticsAddress string
insecureDiagnostics bool
shardKey string
workers int
concurrentReconciles int
agentInMgmtCluster bool
reportMode controllers.ReportMode
tmpReportMode int
restConfigQPS float32
restConfigBurst int
webhookPort int
syncPeriod time.Duration
conflictRetryTime time.Duration
healthErrorRetryTime time.Duration
version string
healthAddr string
profilerAddress string
driftDetectionConfigMap string
luaConfigMap string
capiOnboardAnnotation string
disableCaching bool
disableTelemetry bool
autoDeployDependencies bool
registry string
luaCallStackSize int
luaRegistrySize int
helmChartUpdateCheckInterval time.Duration
)

const (
Expand Down Expand Up @@ -297,6 +298,10 @@ func initFlags(fs *pflag.FlagSet) {
fmt.Sprintf("The minimum interval at which health check failures are retried. Default: %d seconds",
defaultHealthErrorRetryTime))

fs.DurationVar(&helmChartUpdateCheckInterval, "helm-chart-update-check-interval", time.Hour,
"Interval at which Sveltos checks whether newer versions of deployed Helm charts have been "+
"published upstream (HTTP repositories and OCI registries). Set to 0 to disable.")

// AutoDeployDependencies enables automatic deployment of prerequisite profiles.
//
// Profile instances can specify dependencies on other profiles using the
Expand Down Expand Up @@ -671,6 +676,15 @@ func startControllersAndWatchers(ctx context.Context, mgr manager.Manager) {
setupLog.Error(err, "unable to create controller", "controller", "ClusterPromotion")
os.Exit(1)
}

// Needs a fleet-wide view of every ClusterSummary to dedup chart keys correctly, so
// this only ever runs on the default (unsharded) deployment, same as the reconcilers
// started above. Running it per-shard would give no benefit (chart-key dedup is
// inherently fleet-wide) and would reintroduce cross-shard inconsistency.
if helmChartUpdateCheckInterval > 0 {
go controllers.RunHelmChartUpdateChecker(ctx, mgr.GetClient(), helmChartUpdateCheckInterval,
ctrl.Log.WithName("helm-chart-update-checker"))
}
}

clusterSummaryReconciler := getClusterSummaryReconciler(ctx, mgr)
Expand Down
45 changes: 45 additions & 0 deletions config/crd/bases/config.projectsveltos.io_clustersummaries.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2262,15 +2262,56 @@ spec:
directly managed by ClusterProfile.
items:
properties:
chartName:
description: |-
ChartName, RepositoryName, RepoURL, and ChartVersion mirror the fully resolved
(post-template) HelmChart entry that produced this release, captured at deploy time.
Never set for Flux-source-backed charts (Flux owns version resolution there).
type: string
chartVersion:
type: string
conflictMessage:
description: |-
Status indicates whether ClusterSummary can manage the helm
chart or there is a conflict
type: string
credentialsSecretRef:
description: |-
CredentialsSecretRef is the resolved secret reference (if any) used to authenticate
against RepoURL, captured at deploy time. Only the reference is stored, never secret
contents.
properties:
name:
description: name is unique within a namespace to reference
a secret resource.
type: string
namespace:
description: namespace defines the space within which the
secret name must be unique.
type: string
type: object
x-kubernetes-map-type: atomic
failureMessage:
description: FailureMessage provides the specific error from
the Helm engine for this release
type: string
lastCheckedTime:
description: LastCheckedTime is when LatestVersion/LatestPatchVersion
were last evaluated.
format: date-time
type: string
latestPatchVersion:
description: |-
LatestPatchVersion is the highest published version sharing ChartVersion's
major.minor, if greater than ChartVersion. Distinguishes "a same-minor patch bump is
available" from "a newer minor/major line exists" (LatestVersion).
type: string
latestVersion:
description: |-
LatestVersion is the highest version currently published upstream for this chart, if
greater than ChartVersion. Populated by a periodic background check, independent of
the reconcile loop. Detection only: Sveltos never mutates ChartVersion based on this.
type: string
patchesHash:
description: PatchesHash represents of a unique value for the
patches section
Expand All @@ -2285,6 +2326,10 @@ spec:
be installed
minLength: 1
type: string
repoURL:
type: string
repositoryName:
type: string
status:
description: |-
Status indicates whether ClusterSummary can manage the helm
Expand Down
65 changes: 65 additions & 0 deletions controllers/clustersummary_predicates_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import (
"k8s.io/klog/v2/textlogger"
"sigs.k8s.io/controller-runtime/pkg/event"

configv1beta1 "github.com/projectsveltos/addon-controller/api/v1beta1"
"github.com/projectsveltos/addon-controller/controllers"
libsveltosv1beta1 "github.com/projectsveltos/libsveltos/api/v1beta1"
)
Expand Down Expand Up @@ -338,3 +339,67 @@ var _ = Describe("ClusterProfile Predicates: FluxSourcePredicates", func() {
Expect(result).To(BeFalse())
})
})

var _ = Describe("Clustersummary Predicates: ClusterSummaryPredicate", func() {
var logger logr.Logger
var clusterSummary *configv1beta1.ClusterSummary

BeforeEach(func() {
logger = textlogger.NewLogger(textlogger.NewConfig())
clusterSummary = &configv1beta1.ClusterSummary{
ObjectMeta: metav1.ObjectMeta{
Name: randomString(),
},
Status: configv1beta1.ClusterSummaryStatus{
HelmReleaseSummaries: []configv1beta1.HelmChartSummary{
{
ReleaseName: randomString(),
ReleaseNamespace: randomString(),
Status: configv1beta1.HelmChartStatusManaging,
ChartName: randomString(),
RepositoryName: randomString(),
RepoURL: testRepoURLBitnami,
ChartVersion: testChartVersion100,
},
},
},
}
})

It("Update returns false when only LatestVersion/LatestPatchVersion/LastCheckedTime change", func() {
clusterSummaryPredicate := controllers.ClusterSummaryPredicate{Logger: logger}

oldClusterSummary := clusterSummary.DeepCopy()

newLatest := "1.1.0"
lastChecked := metav1.Now()
clusterSummary.Status.HelmReleaseSummaries[0].LatestVersion = &newLatest
clusterSummary.Status.HelmReleaseSummaries[0].LastCheckedTime = &lastChecked

e := event.UpdateEvent{
ObjectNew: clusterSummary,
ObjectOld: oldClusterSummary,
}

result := clusterSummaryPredicate.Update(e)
Expect(result).To(BeFalse())
})

It("Update returns true when FeatureSummaries change", func() {
clusterSummaryPredicate := controllers.ClusterSummaryPredicate{Logger: logger}

oldClusterSummary := clusterSummary.DeepCopy()

clusterSummary.Status.FeatureSummaries = []configv1beta1.FeatureSummary{
{FeatureID: libsveltosv1beta1.FeatureHelm, Status: libsveltosv1beta1.FeatureStatusProvisioned},
}

e := event.UpdateEvent{
ObjectNew: clusterSummary,
ObjectOld: oldClusterSummary,
}

result := clusterSummaryPredicate.Update(e)
Expect(result).To(BeTrue())
})
})
Loading