PreReconciliationOwnerChecker
Description
PreReconciliationOwnerChecker is a specialized variant of PreReconciliationChecker that validates only the owner’s state before reconciliation, without accessing the resource itself. This extension is invoked before any ARM operations, including GET requests on the resource being reconciled.
The key difference from PreReconciliationChecker is that this extension avoids performing GET operations on the resource itself, only checking the parent/owner resource. This is critical for resources where the owner’s state can completely block access to the child resource.
Interface Definition
See the PreReconciliationOwnerChecker interface definition in the source code.
Motivation
The PreReconciliationOwnerChecker extension exists to handle a specific class of Azure resources where:
- Owner state blocks all access: The parent resource’s state can prevent any operations on child resources, including GET
- Cannot determine child state: You cannot query the child resource to check its state when the owner is in certain states
- Avoid wasted API calls: Attempting to GET or PUT a child when the owner blocks access wastes API quota and generates errors
- Owner-dependent access: Some Azure services completely shut down child resources when the parent is in maintenance, updating, or powered-off states
The most notable example is Azure Data Explorer (Kusto), where you cannot even GET a database when the cluster is powered off or updating. Without this extension, the controller would repeatedly attempt to access the database, failing each time and consuming request quota.
When to Use
Implement PreReconciliationOwnerChecker when:
- ✅ The owner’s state can block all access to the child resource, including GET operations
- ✅ You need to avoid GET requests on the resource itself
- ✅ The parent resource has states that completely prevent child access (powered off, updating, locked)
- ✅ Attempting operations when the owner is in certain states always fails
- ✅ You want to avoid wasting API quota on operations that will definitely fail
Do not use PreReconciliationOwnerChecker when:
- ❌ You can safely GET the resource regardless of owner state (use
PreReconciliationCheckerinstead) - ❌ You need access to the resource’s current state to make the decision
- ❌ The owner’s state doesn’t affect access to the child
- ❌ The check can be done after retrieving the resource
PreReconciliationOwnerChecker vs PreReconciliationChecker
Understanding the difference is critical:
| Aspect | PreReconciliationOwnerChecker | PreReconciliationChecker |
|---|---|---|
| When invoked | Before any ARM calls, including GET | After GET, before PUT/PATCH |
| Resource access | No - only owner checked | Yes - fresh resource status available |
| Use case | Owner blocks all access | Validation based on current state |
| GET avoidance | Yes - no GET performed | No - GET already performed |
| Parameters | Only owner |
Both obj and owner |
Rule of thumb: If you can GET the resource to check its state, use PreReconciliationChecker. If even GET fails when the owner is in certain states, use PreReconciliationOwnerChecker.
Example: Kusto Database Owner State Check
Problem: Kusto databases cannot be accessed at all when the cluster is stopped or updating.
Solution: Check cluster state before attempting any database operations.
// Block on: Creating, Updating, Deleting, Stopped, Stopping
// Allow on: Running, Succeeded
See the full implementation in database_extensions.go.
Key aspects of this implementation:
- Owner type assertion: Checks if owner is a Kusto Cluster
- Nil handling: Gracefully handles nil owner (ARM ID references)
- State checking: Examines cluster’s provisioning state
- Clear blocking messages: Provides specific reason for blocking
- Helper function: Encapsulates state-checking logic
- Calls next: Proceeds when cluster is in acceptable state
Check Results
The extension returns one of two results, or an error:
Proceed
return extensions.ProceedWithReconcile(), nil
- Owner state permits reconciliation
- Reconciliation will continue (GET will be attempted)
- Normal reconciliation flow proceeds
Block
return extensions.BlockReconcile("parent is updating"), nil
- Owner state blocks reconciliation
- No GET or other operations attempted on the resource
- Resource requeued to try again later
- Condition set with the blocking reason
Error
return extensions.PreReconcileCheckResult{}, fmt.Errorf("check failed: %w", err)
- The check itself failed
- Error condition set on resource
- Reconciliation blocked until error resolved
Reconciliation Flow
Understanding where this fits in the reconciliation process:
- Resource needs reconciliation: Controller picks up resource
- Owner resolution: Owner resource identified and fetched
- PreReconciliationOwnerChecker invoked: Extension checks owner state ← YOU ARE HERE
- Decision point:
- If blocked: Stop here, requeue, set condition
- If proceed: Continue to next step
- GET resource: Fetch resource from Azure (only if not blocked)
- PreReconciliationChecker: Check resource state (if implemented)
- ARM operations: PUT/PATCH/DELETE as needed
Testing
When testing PreReconciliationOwnerChecker extensions:
- Test with nil owner: Verify handling when owner is nil
- Test with wrong owner type: Verify graceful handling
- Test blocking states: Cover all states that should block
- Test proceed states: Verify reconciliation proceeds when appropriate
- Test error handling: Verify proper error returns
Important Notes
- No resource access: You do not receive the resource being reconciled
- Owner only: Make decisions based solely on owner state
- Earlier in flow: Runs before GET, unlike PreReconciliationChecker
- Nil owner: Always handle the nil owner case gracefully
- Type assertions: Verify owner is expected type before accessing fields
- Call next(): Call the next checker in the chain when checks pass
- Clear reasons: Provide helpful blocking messages for users
- Logging: Log decisions to help debugging
Related Extension Points
- PreReconciliationChecker: Check resource state (use this unless you need owner-only checks)
- PostReconciliationChecker: Validate after reconciliation
Best Practices
- Prefer PreReconciliationChecker: Use this only when necessary
- Handle nil owner: Always check for nil before dereferencing
- Type assert safely: Verify owner type before accessing fields
- Document blocking states: Comment which states block and why
- Use helper functions: Encapsulate state-checking logic
- Log decisions: Help debugging by logging why checks block
- Clear messages: Users need to understand why reconciliation is blocked
- Call next(): Enable check chaining
- Test thoroughly: Cover all owner states and edge cases