improvements jan2025 (#6)

* feat(controller): add lazy watcher, improve resource usage and add pattern validation

- [x] Add cache sync health check for readiness probe verification
- [x] Create namespace lister with API reader support for fresh label queries
- [x] Add pattern validation with warning logs for invalid glob patterns
- [x] Implement lazy watcher initialization mode to scan for active resources
- [x] Add requeue delay to namespace reconciler for cache settlement
- [x] Replace custom containsString with slices.Contains from stdlib
- [x] Add structured logging context to reconcilers (kind, group, version)
- [x] Improve error variable naming for clarity in nested conditions
- [x] Add nil-safe label access in namespace reconciler setup
- [x] Add APIReader to namespace and source reconcilers for fresh data
- [x] Improve type assertions with proper error handling in mirror operations
- [x] Reorder struct fields for consistency and readability
- [x] Add comprehensive pattern validation tests and validation API

* feat(controller): add lazy watcher, improve resource usage and add pattern validation

- [x] Add circuit breaker for reconciliation failure tracking and prevention
- [x] Implement granular registration state tracking (not-registered, source-only, fully-registered)
- [x] Add lazy controller initialization for active resource types only
- [x] Consolidate namespace listing into single API call for efficiency
- [x] Add mirror creation verification to catch webhook rejections
- [x] Implement high-cardinality resource detection and warnings
- [x] Add source deletion check in mirror reconciler to prevent races
- [x] Preserve transformation annotations on errors in mirror reconciliation
- [x] Expand constants documentation with labels vs annotations design rationale
- [x] Add comprehensive test coverage for circuit breaker and registration states
- [x] Add mutation-safety tests for hash computation

* fixup! feat(controller): add lazy watcher, improve resource usage and add pattern validation
This commit is contained in:
2026-01-14 13:07:11 +00:00
committed by GitHub
parent 4f8e2783cf
commit 096dca47d1
22 changed files with 1937 additions and 266 deletions
+115 -2
View File
@@ -168,12 +168,12 @@ func TestComputeContentHash_ConfigMap(t *testing.T) {
name: "binaryData included in hash",
cm1: &corev1.ConfigMap{
BinaryData: map[string][]byte{
"file": []byte{0x00, 0x01, 0x02},
"file": {0x00, 0x01, 0x02},
},
},
cm2: &corev1.ConfigMap{
BinaryData: map[string][]byte{
"file": []byte{0x00, 0x01, 0xFF},
"file": {0x00, 0x01, 0xFF},
},
},
wantSame: false,
@@ -484,6 +484,119 @@ func mustComputeHash(t *testing.T, obj runtime.Object) string {
return hash
}
// TestComputeContentHash_NoMutation verifies that hash computation doesn't mutate the input object.
// This is critical because NestedMap can modify the underlying map.
func TestComputeContentHash_NoMutation(t *testing.T) {
t.Run("unstructured object is not mutated", func(t *testing.T) {
// Create an unstructured object with nested spec
original := &unstructured.Unstructured{
Object: map[string]interface{}{
"apiVersion": "v1",
"kind": "Custom",
"metadata": map[string]interface{}{
"name": "test-resource",
"namespace": "default",
"annotations": map[string]interface{}{
constants.AnnotationTransform: `{"rules":[{"field":"spec.value","action":"base64encode"}]}`,
},
},
"spec": map[string]interface{}{
"field1": "value1",
"nested": map[string]interface{}{
"deep": "data",
},
},
"status": map[string]interface{}{
"condition": "Ready",
},
},
}
// Deep copy the original to compare after hash computation
expectedCopy := original.DeepCopy()
// Compute hash multiple times
hash1, err := ComputeContentHash(original)
require.NoError(t, err)
hash2, err := ComputeContentHash(original)
require.NoError(t, err)
// Hashes should be consistent (object wasn't modified)
assert.Equal(t, hash1, hash2, "hash should be consistent across calls")
// Original object should be unchanged
assert.Equal(t, expectedCopy.Object, original.Object, "original object should not be mutated")
})
t.Run("secret is not mutated", func(t *testing.T) {
secret := &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: "test-secret",
Namespace: "default",
Annotations: map[string]string{
constants.AnnotationTransform: `{"rules":[]}`,
},
},
Data: map[string][]byte{
"password": []byte("secret123"),
},
Type: corev1.SecretTypeOpaque,
}
// Copy for comparison
originalData := make(map[string][]byte)
for k, v := range secret.Data {
originalData[k] = append([]byte(nil), v...)
}
originalAnnotations := make(map[string]string)
for k, v := range secret.Annotations {
originalAnnotations[k] = v
}
// Compute hash
_, err := ComputeContentHash(secret)
require.NoError(t, err)
// Verify no mutation
assert.Equal(t, originalData, secret.Data, "secret data should not be mutated")
assert.Equal(t, originalAnnotations, secret.Annotations, "secret annotations should not be mutated")
})
t.Run("configmap is not mutated", func(t *testing.T) {
cm := &corev1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Name: "test-cm",
Namespace: "default",
},
Data: map[string]string{
"config.yaml": "key: value",
},
BinaryData: map[string][]byte{
"binary": {0x00, 0x01, 0x02},
},
}
// Copy for comparison
originalData := make(map[string]string)
for k, v := range cm.Data {
originalData[k] = v
}
originalBinaryData := make(map[string][]byte)
for k, v := range cm.BinaryData {
originalBinaryData[k] = append([]byte(nil), v...)
}
// Compute hash
_, err := ComputeContentHash(cm)
require.NoError(t, err)
// Verify no mutation
assert.Equal(t, originalData, cm.Data, "configmap data should not be mutated")
assert.Equal(t, originalBinaryData, cm.BinaryData, "configmap binary data should not be mutated")
})
}
// Benchmark tests
func BenchmarkComputeContentHash_Secret(b *testing.B) {
secret := &corev1.Secret{