Repository navigation
Adoption and filter import can reconcile incomplete listed resources #1007
Description
Problem description
The generic reconciler uses resources returned by list operations directly for reconciliation and status writing. It does not require a full fetch after selecting a resource for adoption or filter-based import.
Some controllers return less information from their list paths than from GetOSResourceByID(). Missing observations can consequently be interpreted as empty state.
A confirmed example is Server interfaces:
GetOSResourceByID()fetches both the Server and its attached interfaces.wrapServers(), used by adoption and filter import, explicitly setsInterfaces: nil.- Port-attachment reconciliation and status writing consume that interface list without first populating it.
The comment in wrapServers() says interfaces will be fetched during reconciliation, but the generic flow does not guarantee that fetch.
Steps to reproduce
- Create an OpenStack Server with attached interfaces.
- Wait until the Server is
ACTIVE. - Create an unmanaged ORC Server using an import filter that uniquely selects it.
- Leave periodic resync disabled.
- Inspect
status.resource.interfacesafter import completes.
Actual behavior
The imported Server can report no interfaces despite having attached ports.
Managed adoption has related risks: it can attempt to attach already-attached ports and cannot identify undesired interfaces for detachment.
Another reconciliation may populate the missing information, but one is not guaranteed after reconciliation is considered complete.
Expected behavior
Reconciliation and status writing should use a complete observation of the selected resource. Data that has not been fetched must not be treated as an observed empty collection.
Affected code
internal/controllers/generic/reconciler/resource_actions.go: filter import and adoption return listed resources directly.internal/controllers/server/actuator.go:GetOSResourceByID(),wrapServers(), andreconcilePortAttachments().internal/controllers/server/status.go: observed interface status.
The proposed Group membership implementation in #985 has the same pattern: GetGroup() populates membership, while ListGroups() leaves UserIDs unset.
Suggested approach
Consider fetching the selected resource through GetOSResourceByID() after establishing a unique list match, before reconciliation or status writing. Alternatively, establish and enforce a contract that controller list paths return complete observations.
Regression coverage
- Unmanaged filter import of an active Server with existing interfaces.
- Managed adoption of a Server with already-attached desired ports.
- Group adoption and filter import with existing members, once membership support is added.
ORC version
v3.0.0-pre1
Additional information
No response
Activity
winiciusallan commentedon Oct 29, 2026
One thing that caught me: I can see the resource having an empty
status.resource.interfaces, but would not, eventually, the controller reconcile the port attachments viareconcilePortAttachments?zunken1337 commentedon Oct 30, 2026
reconcilePortAttachmentsonly runs for managed objects, so for an unmanaged import nothing fixes it: status is written from the list result and nothing triggers another reconcile onceProgressingis False and resync is disabled. In practice the status ID write usually causes one more reconcile, which is why the kuttl step in #1032 passes without the fix, but it isn't guaranteed.For managed adoption it does run, but with
Interfacesnil it tries to attach ports that are already attached and Nova returns an error. The next reconcile fetches by ID and recovers, so it's a transient error rather than a wrong state.