Skip to content

SecurityGroup with a deliberately empty rules list never reaches Available #960

Description

@zunken1337

What happened

A SecurityGroup whose spec.resource.rules is explicitly set to an empty list (rules: []) -
e.g. a placeholder security-group profile that intentionally starts with no openings, meant to
have rules added to it later - never reaches Available: True. It stays permanently in:

status:
  conditions:
  - type: Available
    status: "False"
    reason: Progressing
    message: Waiting for OpenStack resource to be ready

...despite the real OpenStack security group existing (it has a real status.id) and genuinely
having zero rules, matching the spec exactly. The object just polls forever (every 15s) and never
settles.

Use case this affects

This showed up in a real GitOps repo onboarding a HyperShift/OpenStack cluster: a
mgmt-ssh-style security-group profile is created with rules: [] by design (default-deny,
rules added later only if/when actually needed), separate from a core-cluster profile that
does have rules. core-cluster reaches Available: True correctly; the empty mgmt-ssh one
never does. This is possibly a narrow pattern - "intentionally-empty placeholder security group" -
so it may only be us hitting it, but it's a real, reproducible bug either way, not a
misconfiguration on our side (confirmed the group is correctly attached to real ports via Neutron
directly, independent of K-ORC's own stuck status).

Root cause

internal/controllers/securitygroup/status.go's ResourceAvailableStatus:

resourceSpec := orcObject.Spec.Resource
if resourceSpec != nil && resourceSpec.Rules != nil {
	resourceStatus := orcObject.Status.Resource
	if resourceStatus == nil || resourceStatus.Rules == nil {
		return metav1.ConditionFalse, progress.WaitingOnOpenStack(progress.WaitingOnReady, securityGroupAvailablePollingPeriod)
	}
	...
}

An empty []SecurityGroupRule{} is a non-nil slice in Go, so resourceSpec.Rules != nil is true
even when the list is deliberately empty. Separately, ApplyResourceStatus (same file) only calls
WithRules(...) inside a loop over osResource.Rules - when the real OpenStack resource
genuinely has zero rules, that loop runs zero times, so WithRules is never called at all, and
status.resource.rules is left permanently nil. The resourceStatus.Rules == nil check above
therefore stays true forever for a genuinely-empty security group, and the object can never pass
it to reach the (already-correct) comparison against the freshly-fetched osResource.Rules a few
lines further down.

Will follow up with a PR shortly - found and fixed alongside this issue, small change (replace the
two checks against orcObject.Status.Resource.Rules with the one already-present, already-correct
comparison against osResource.Rules directly, which has no nil/empty ambiguity since it's this
reconcile's own fresh read).

Activity

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

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions