Skip to content

Fix protocol changes on existing load balancer rules - #104

Open
vishesh92 wants to merge 1 commit into
mainfrom
fix-protocol-toggle
Open

Fix protocol changes on existing load balancer rules#104
vishesh92 wants to merge 1 commit into
mainfrom
fix-protocol-toggle

Conversation

@vishesh92

Copy link
Copy Markdown
Member

Fixes #2.

Toggling service.beta.kubernetes.io/cloudstack-load-balancer-proxy-protocol on an
existing LoadBalancer service wedges reconciliation permanently:

error creating load balancer rule a192...-tcp-proxy-80: CloudStack API error 537:
The range specified, 80-80, conflicts with rule FirewallRule {...} which has 80-80

Cause: rule names embed the protocol (<lb>-<protocol>-<port>) and rules are looked
up by name, so a protocol change misses the lookup and tries to create a rule on a port
the old rule still holds. The in-place update was already written but unreachable — a
name-keyed lookup can never return a rule whose protocol differs from the one requested.

Changes

  • findLoadBalancerRule matches on an exact name, then falls back to
    (public IP, IP protocol, public port) — the tuple CloudStack enforces uniqueness on.
    A proxy-protocol toggle now resolves to the existing rule and updates it in place.
    Rules on a stale IP are pruned rather than matched, which used to strand their
    firewall rule.
  • Renames the rule via SetName so the name stops contradicting its protocol.
  • Reconciles in three phases: resolve, prune, apply. Rules blocking a needed port are
    deleted before the creates, everything else after, so a cleanup failure can't take a
    service down. Blocking is keyed on port alone — detectRulesConflict never exempts
    LoadBalancing pairs with differing protocols.

Also fixed:

  • Proxy protocol was unusable on VPC tiers, independently of [OLD] Changing from TCP to TCP Proxy doesn't work #2: updateNetworkACL
    created ACLs with CSProtocol() (tcp-proxy, which CloudStack rejects) while
    filtering with IPProtocol(). Both now use IPProtocol().
  • Multi-CIDR services churned every sync — an existing rule's Cidrlist was split on
    " " while CloudStack returns it comma-separated.
  • Startup panicked instead of erroring on a management-server version with fewer than
    three parts.

Copilot AI lite review requested due to automatic review settings August 26, 2026 12:22
@codecov-commenter

codecov-commenter commented Aug 26, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 75.79618% with 38 lines in your changes missing coverage. Please review.
✅ Project coverage is 56.99%. Comparing base (151452f) to head (bc832c4).

Files with missing lines Patch % Lines
cloudstack_loadbalancer.go 75.00% 26 Missing and 12 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #104      +/-   ##
==========================================
+ Coverage   50.05%   56.99%   +6.94%     
==========================================
  Files           4        4              
  Lines         975     1058      +83     
==========================================
+ Hits          488      603     +115     
+ Misses        473      425      -48     
- Partials       14       30      +16     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes reconciliation getting wedged when toggling service.beta.kubernetes.io/cloudstack-load-balancer-proxy-protocol on an existing LoadBalancer Service by resolving existing CloudStack LB rules by their uniqueness tuple (public IP, IP protocol, public port) and updating rules in-place (including renaming) rather than attempting conflicting creates. Also includes related robustness fixes around CIDR list comparison, VPC ACL protocol handling, and management-server version parsing.

Changes:

  • Reworks LB rule reconciliation into resolve/prune/apply phases, with rule lookup falling back from name to (public IP, IP protocol, public port) to support protocol toggles.
  • Normalizes CIDR list parsing for rule comparisons and gates CIDR updates on CloudStack version support.
  • Hardens management server version parsing (avoids panics on short versions) and expands unit test coverage, including regression tests for issue #2.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated no comments.

Show a summary per file
File Description
README.md Documents that proxy-protocol toggling updates the rule in-place without port interruption.
cloudstack.go Makes management-server version parsing resilient to short/4-part version strings.
cloudstack_test.go Adds coverage for short/empty version strings to prevent panics and validate parsing behavior.
cloudstack_loadbalancer.go Implements tuple-based LB rule resolution, phased prune/apply reconciliation, CIDR list normalization, and VPC ACL protocol fix.
cloudstack_loadbalancer_test.go Adds tests for CIDR splitting, tuple-based rule matching, in-place protocol toggles, phased pruning behavior, and VPC ACL behavior.
Suppressed comments (1)

cloudstack_loadbalancer.go:890

  • When a rule must be recreated, checkLoadBalancerRule deletes it in CloudStack but leaves it in lb.rules. That leftover entry is then treated as obsolete and pruned, which can trigger a second DeleteLoadBalancerRule call (and potentially fail reconciliation with a "not found"/API error) even though the rule was already deleted in the resolve phase.

Remove the rule from lb.rules immediately after a successful delete so it can’t be pruned again later in the same reconciliation.

		// Delete the load balancer rule so we can create a new one using the new values.
		if err := lb.deleteLoadBalancerRule(lbRule); err != nil {
			return nil, false, err
		}
		return nil, false, nil

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@vishesh92
vishesh92 force-pushed the fix-protocol-toggle branch from 345a563 to bc832c4 Compare August 27, 2026 07:59
Copilot AI review requested due to automatic review settings August 27, 2026 07:59

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[OLD] Changing from TCP to TCP Proxy doesn't work

3 participants