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).
What happened
A
SecurityGroupwhosespec.resource.rulesis 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:...despite the real OpenStack security group existing (it has a real
status.id) and genuinelyhaving 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 withrules: []by design (default-deny,rules added later only if/when actually needed), separate from a
core-clusterprofile thatdoes have rules.
core-clusterreachesAvailable: Truecorrectly; the emptymgmt-sshonenever 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'sResourceAvailableStatus:An empty
[]SecurityGroupRule{}is a non-nil slice in Go, soresourceSpec.Rules != nilis trueeven when the list is deliberately empty. Separately,
ApplyResourceStatus(same file) only callsWithRules(...)inside a loop overosResource.Rules- when the real OpenStack resourcegenuinely has zero rules, that loop runs zero times, so
WithRulesis never called at all, andstatus.resource.rulesis left permanentlynil. TheresourceStatus.Rules == nilcheck abovetherefore 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.Rulesa fewlines 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.Ruleswith the one already-present, already-correctcomparison against
osResource.Rulesdirectly, which has no nil/empty ambiguity since it's thisreconcile's own fresh read).