Skip to content

Commit e7d8343

Browse files
Merge pull request #1152 from blublinsky/update
Modifying update logic
2 parents 30bcceb + 3ddc870 commit e7d8343

37 files changed

+3184
-1603
lines changed

AGENTS.md

Lines changed: 115 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@ OLSConfigReconciler.Reconcile() →
3838

3939
### Resource Management
4040
- **Pattern**: Get → Check if exists → Create/Update with error wrapping
41-
- **Caching**: Uses `r.stateCache` for hash-based change detection
4241
- **Annotations**: Extensive use for watching/change detection
42+
- **Utilities**: Common helpers in `utils/` for resource requirements, volume permissions, etc.
4343

4444
## Testing Conventions
4545

@@ -99,6 +99,10 @@ var _ = Describe("Component Name", func() {
9999
- `api/v1alpha1/olsconfig_types.go` - Main CRD struct definitions
100100
- Includes: `LLMSpec`, `OLSSpec`, `DeploymentConfig`, etc.
101101

102+
### Entry Point & Configuration
103+
- `cmd/main.go` - Operator entry point with command-line flags and watcher configuration
104+
- Contains `WatcherConfig` - Declarative configuration for external resource watching
105+
102106
### Tests to Check
103107
- **Unit Tests** (co-located with source):
104108
- `internal/controller/*_test.go` - Main controller tests
@@ -210,18 +214,120 @@ var _ = Describe("<Component> Name", func() {
210214

211215
## State Management
212216

213-
### Hash-Based Change Detection
217+
### ResourceVersion-Based Change Detection
218+
219+
The operator uses Kubernetes' built-in ResourceVersion tracking for owned resources:
220+
214221
```go
215-
r.stateCache[OLSConfigHashStateCacheKey] = configHash
216-
r.stateCache[LLMProviderHashStateCacheKey] = providerHash
222+
// Owned resources are tracked automatically by controller-runtime
223+
// Changes detected via ResourceVersion comparison
224+
deployment := &appsv1.Deployment{}
225+
err := r.Get(ctx, types.NamespacedName{Name: deploymentName}, deployment)
226+
// ResourceVersion changes automatically trigger reconciliation
217227
```
218228

229+
### Multi-Level Watcher System
230+
231+
The operator implements a sophisticated **three-layer watching architecture** for external resources:
232+
233+
**Layer 1: Predicate Filtering (Performance)**
234+
- Fast O(1) checks at Kubernetes watch level
235+
- Filters 99% of irrelevant events before processing
236+
- Methods: `shouldWatchSecret()`, `shouldWatchConfigMap()`
237+
238+
**Layer 2: Data Comparison (Correctness)**
239+
- Deep comparison using `apiequality.Semantic.DeepEqual()`
240+
- Only triggers on actual data changes, not metadata
241+
- Handlers: `SecretUpdateHandler`, `ConfigMapUpdateHandler`
242+
- Handles Create events for recreated resources (with owner filtering)
243+
- Skips operator-owned resources managed via `Owns()` relationship
244+
245+
**Layer 3: Restart Logic (Business)**
246+
- Data-driven configuration via `WatcherConfig`
247+
- Maps resources to affected deployments
248+
- Backend-aware restart decisions
249+
250+
### Watcher Configuration
251+
252+
All watcher behavior is centralized in `cmd/main.go` via `WatcherConfig`:
253+
254+
```go
255+
watcherConfig := &utils.WatcherConfig{
256+
Secrets: utils.SecretWatcherConfig{
257+
SystemResources: []utils.SystemSecret{
258+
{Name: "pull-secret", Namespace: "openshift-config",
259+
AffectedDeployments: []string{"console-ui"}},
260+
},
261+
},
262+
ConfigMaps: utils.ConfigMapWatcherConfig{
263+
SystemResources: []utils.SystemConfigMap{
264+
{Name: "kube-root-ca.crt",
265+
AffectedDeployments: []string{"ACTIVE_BACKEND"}},
266+
},
267+
},
268+
}
269+
```
270+
271+
**Key Features:**
272+
- No hardcoded resource names in watcher logic
273+
- Easy to extend (just update configuration)
274+
- `ACTIVE_BACKEND` placeholder auto-resolves based on `--enable-lcore` flag
275+
219276
### Reconciliation Triggers
220-
- Config changes (detected via hash comparison)
221-
- Secret updates (via annotations + `watchers` package)
222-
- ConfigMap updates (via annotations + `watchers` package, triggers rolling restarts)
223-
- Resource deletions/modifications
224-
- Telemetry pull secret changes (special watcher)
277+
278+
- **Config changes**: ResourceVersion comparison on OLSConfig CR
279+
- **Owned resource changes**: Automatic via controller-runtime
280+
- **External secret updates**: Multi-level watcher with annotation + data comparison
281+
- **External configmap updates**: Multi-level watcher with annotation + data comparison + rolling restarts
282+
- **System resources**: Watched by name (telemetry pull secret, OpenShift CA certs)
283+
284+
### Resource Annotation Flow
285+
286+
1. User creates external resource (secret/configmap) referenced in OLSConfig
287+
2. `annotateExternalResources()` runs between Phase 1 & Phase 2
288+
3. Annotation `ols.openshift.io/watch-olsconfig: "cluster"` added
289+
4. Watchers activate via predicate layer
290+
5. Future changes trigger Layer 2 data comparison → Layer 3 restart logic
291+
292+
### External Resource Iteration Pattern
293+
294+
For processing external secrets and configmaps referenced in the CR, use iterator functions:
295+
296+
```go
297+
// Iterate over all external secrets referenced in CR
298+
err := utils.ForEachExternalSecret(cr, func(name string, source string) error {
299+
// Process secret: name = secret name, source = CR field path
300+
return nil
301+
})
302+
303+
// Iterate over all external configmaps referenced in CR
304+
err := utils.ForEachExternalConfigMap(cr, func(name string, source string) error {
305+
// Process configmap: name = configmap name, source = CR field path
306+
return nil
307+
})
308+
```
309+
310+
**Benefits:**
311+
- Centralizes CR traversal logic
312+
- Prevents duplicate code across watchers, annotation, and asset generation
313+
- Supports early termination via error return
314+
- Provides source tracking for debugging
315+
316+
## Common Utility Functions
317+
318+
### Volume Permissions
319+
```go
320+
utils.VolumeDefaultMode = int32(420) // 0644 - Standard readable permissions
321+
utils.VolumeRestrictedMode = int32(0600) // 0600 - Secure, owner-only access
322+
```
323+
324+
### Resource Requirements
325+
```go
326+
// Returns custom resources from CR if specified, otherwise returns defaults
327+
resources := utils.GetResourcesOrDefault(cr.Spec.Component.Resources, defaultResources)
328+
```
329+
330+
225331

226332
## Token-Efficient Debugging Tips
227333

0 commit comments

Comments
 (0)