Skip to content

Adoption and filter import can reconcile incomplete listed resources #1007

Description

@mandre

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 sets Interfaces: 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

  1. Create an OpenStack Server with attached interfaces.
  2. Wait until the Server is ACTIVE.
  3. Create an unmanaged ORC Server using an import filter that uniquely selects it.
  4. Leave periodic resync disabled.
  5. Inspect status.resource.interfaces after 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(), and reconcilePortAttachments().
  • 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

Relevant log output

Activity

  1. added theissue type on Oct 22, 2026
  2. winiciusallan commented on Oct 29, 2026

    @winiciusallan
    Member

    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 via reconcilePortAttachments?

  3. zunken1337 commented on Oct 30, 2026

    @zunken1337
    Contributor

    reconcilePortAttachments only runs for managed objects, so for an unmanaged import nothing fixes it: status is written from the list result and nothing triggers another reconcile once Progressing is 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 Interfaces nil 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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions