Handle enterprise license expiry with grace period#4482
Handle enterprise license expiry with grace period#4482hjiawei wants to merge 2 commits intotigera:masterfrom
Conversation
c8361f1 to
5f6f096
Compare
There was a problem hiding this comment.
Pull request overview
This PR implements enterprise license expiry handling with a grace period. When a license expires, the monitor controller disables metrics scraping (ServiceMonitors) and the log collector controller disables log forwarding (fluentd DaemonSet), while keeping the dataplane running. During the grace period, all components continue running normally with only a log warning. The PR also includes a minor bug fix to SetDegraded that previously produced malformed messages (trailing : ) when err was nil.
Changes:
- New
pkg/controller/utils/license.gowithParseGracePeriod,GetLicenseStatus, andLicenseStatustype, plus moved existing license helpers fromutils.go - Monitor controller and render layer updated to watch license, handle expiry/grace period, and conditionally delete ServiceMonitors
- LogCollector controller and fluentd render layer updated to handle expiry/grace period and conditionally delete the fluentd DaemonSet
- Dependency bumps:
tigera/api(addsGracePeriodfield toLicenseKeyStatus), Kubernetes libraries to v0.34.4, and associated build tooling
Reviewed changes
Copilot reviewed 16 out of 18 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
pkg/controller/utils/license.go |
New file with license status types, parsing, and moved license helpers |
pkg/controller/utils/license_test.go |
Tests for ParseGracePeriod and GetLicenseStatus |
pkg/controller/utils/utils.go |
Removed license helper functions moved to license.go |
pkg/controller/monitor/monitor_controller.go |
Added license watch, expiry check, grace period requeue, and LicenseExpired flag to render config |
pkg/controller/monitor/monitor_controller_test.go |
Tests for license expiry, valid license, and grace period scenarios |
pkg/render/monitor/monitor.go |
Added LicenseExpired flag to Config; ServiceMonitors conditionally moved to toDelete |
pkg/render/monitor/monitor_test.go |
Tests for ServiceMonitor placement based on LicenseExpired flag |
pkg/render/fluentd.go |
Added LicenseExpired flag to FluentdConfiguration; DaemonSet conditionally moved to toDelete |
pkg/render/fluentd_test.go |
Tests for DaemonSet placement based on LicenseExpired flag |
pkg/controller/status/status.go |
Fixed SetDegraded to omit trailing : when err is nil |
pkg/controller/status/status_test.go |
Updated test expectation to match fixed message format |
pkg/controller/logcollector/logcollector_controller.go |
Added grace period check, expiry handling, and LicenseExpired flag to fluentd config |
pkg/controller/logcollector/logcollector_controller_test.go |
Added RemoveDaemonsets mock; added expiry and grace period tests |
go.mod, go.sum, api/go.mod, api/go.sum |
Dependency version bumps |
Makefile |
Build image version bumps consistent with k8s dependency updates |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
When an enterprise license expires (after the grace period elapses),
disable logging (fluentd DaemonSet) and metrics scraping (ServiceMonitors)
while keeping the dataplane running. During the grace period, all
components continue running normally with only a log warning. This aligns
with the enterprise changes that relax license validation so expired
licenses are accepted, with individual components handling degraded behavior.
Changes:
- Add license utility functions in pkg/controller/utils/license.go:
- ParseGracePeriod: parses the "90d" format grace period string from
the typed LicenseKey status.gracePeriod field
- GetLicenseStatus: point-in-time check using a single time.Now() call
returning Valid, InGracePeriod, or Expired status
- Move existing license helpers (FetchLicenseKey, IsFeatureActive,
WaitToAddLicenseKeyWatch) out of utils.go into license.go
- Monitor controller:
- Add license watch and fetch with grace period support
- When expired: set degraded status, move ServiceMonitors to toDelete
- When in grace period: log warning, keep everything running normally
- LogCollector controller:
- Add grace period support to license expiry check
- When expired: set degraded status, move fluentd DaemonSet to toDelete
- When in grace period: log warning, keep everything running normally
- Render layer:
- Add LicenseExpired flag to monitor Config and FluentdConfiguration
- Conditionally move ServiceMonitors/DaemonSet to toDelete when expired
- Bump tigera/api to v0.0.0-20260227222130-df0b9e289a34 which includes
the GracePeriod field in LicenseKeyStatus
5f6f096 to
c23ff81
Compare
|
|
||
| // Should requeue to re-reconcile when the grace period expires. | ||
| Expect(result.RequeueAfter).To(BeNumerically(">", 0)) | ||
| Expect(result.RequeueAfter).To(BeNumerically("~", 89*24*time.Hour, 1*time.Hour)) |
There was a problem hiding this comment.
TIL "~" comparator can be used here.
pkg/controller/utils/license.go
Outdated
| if gracePeriod == "" { | ||
| return 0 | ||
| } | ||
| s := strings.TrimSuffix(gracePeriod, "d") |
There was a problem hiding this comment.
This won't be able to deal with durations that don't use d as a suffix, I think it is better to solve for that as well
There was a problem hiding this comment.
Bare number without unit d is now treated as invalid grace period.
pkg/controller/utils/license_test.go
Outdated
| Entry("invalid string", "abc", time.Duration(0)), | ||
| Entry("negative days", "-5d", time.Duration(0)), | ||
| Entry("number without d suffix", "90", 90*24*time.Hour), |
There was a problem hiding this comment.
All of these seem invalid to me.
There was a problem hiding this comment.
This test case has been updated to require the d unit suffix and no longer accepts bare numbers without a unit.
ParseGracePeriod now requires the "d" suffix and rejects bare integers or other formats. This makes the parser stricter and aligned with the license controller's output format (e.g. "90d"). Also guards against negative values and uses strings.CutSuffix for cleaner suffix handling. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Description
When an enterprise license expires (after the grace period elapses),
disable logging (fluentd DaemonSet) and metrics scraping (ServiceMonitors)
while keeping the dataplane running. During the grace period, all
components continue running normally with only a log warning. This aligns
with the enterprise changes that relax license validation so expired
licenses are accepted, with individual components handling degraded behavior.
Changes:
Add license utility functions in pkg/controller/utils/license.go:
the typed LicenseKey status.gracePeriod field
returning Valid, InGracePeriod, or Expired status
WaitToAddLicenseKeyWatch) out of utils.go into license.go
Monitor controller:
LogCollector controller:
Render layer:
Bump tigera/api to v0.0.0-20260227222130-df0b9e289a34 which includes
the GracePeriod field in LicenseKeyStatus
Release Note
For PR author
make gen-filesmake gen-versionsFor PR reviewers
A note for code reviewers - all pull requests must have the following:
kind/bugif this is a bugfix.kind/enhancementif this is a a new feature.enterpriseif this PR applies to Calico Enterprise only.